sound updates for 5.19-rc1

Not much dramatic changes at this time, but we've received quite
 a lot of changes for ASoC, while there are still a few fixes and
 quirks for usual HD- and USB-auido.  Here are some highlights.
 
 * ASoC:
 - Overhaul of endianness specification for data formats, avoiding
   needless restrictions due to CODECs
 - Initial stages of Intel AVS driver merge
 - Introduction of v4 IPC mechanism for SOF
 - TDM mode support for AK4613
 - Support for Analog Devices ADAU1361, Cirrus Logic CS35L45, Maxim
   MAX98396, MediaTek MT8186, NXP i.MX8 micfil and SAI interfaces,
   nVidia Tegra186 ASRC, and Texas Instruments TAS2764 and TAS2780
 
 * Others
 - A few regression fixes after the USB-audio endpoint management
   refactoring
 - More enhancements for Cirrus HD-audio codec support (still ongoing)
 - Addition of generic serial MIDI driver
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmKOEiAOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE96FxAAnoVCecFK955fWInCULe15xYpi9kqngDSLAQk
 k6TkbP8AFyX+3PbIb9YVK9u+fLBaZzdK/ZIRqZNfb5T4q8tVTHphg2P+SNB36qaD
 nTTaEQ6dr6VUJO3fwwVBa3NJ+rGPr8KMKLlQGCg/I8HKdFeW2t/mV1YZI/ZxM7Or
 MXu3F5dt3yVXXMgUb33if+atYCXOwJ9YIqe1WHE4oPTtfOhbwiIdFeHgg88Kq7vJ
 ep7PCbyJ0rqfA9BIAnBfQuD9ZoaS7mKlo9xgyauNBzWnbRVd7dYyUnaxH++XLPPS
 GS0MEgftJfmUay6o++I7qrhoTyMKMHN/CU+6RlR1GD6WBpBhQ6T+poLkFDvKqbL8
 kvFEBFrEf0soeAKkUinzl1wCJnzWvpq2PF0EewQp03A3vOL5MOzGdId1wLKLmbCw
 Z0e0HAKTP4/AQeBluLo/SjiNoeSEU76xYYv8tFGv531ybIhvsF0nm/Suv4VZcy0V
 9tr2gLSORDLTBqSJqCf1JgN8oJht0QLirzgSekk8HUvx1JnIwwAaH1Dvy1DMrjyu
 TQ6oRyDS2giHKh7FItv3+U+HE1CkA89dzDvGrIbKrT6xkodHGzLNr0DxaDGuR11w
 H9f9oFEnGBpBxWmfLkGTa8+oBenTz8YRm4Ti8xhZkJkD1ys/4fjasAYoIKJqdnxH
 iG1DWic=
 =5qBk
 -----END PGP SIGNATURE-----

Merge tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "Not much dramatic changes at this time, but we've received quite a lot
  of changes for ASoC, while there are still a few fixes and quirks for
  usual HD- and USB-auido. Here are some highlights.

  ASoC:

   - Overhaul of endianness specification for data formats, avoiding
     needless restrictions due to CODECs

   - Initial stages of Intel AVS driver merge

   - Introduction of v4 IPC mechanism for SOF

   - TDM mode support for AK4613

   - Support for Analog Devices ADAU1361, Cirrus Logic CS35L45, Maxim
     MAX98396, MediaTek MT8186, NXP i.MX8 micfil and SAI interfaces,
     nVidia Tegra186 ASRC, and Texas Instruments TAS2764 and TAS2780

  Others:

   - A few regression fixes after the USB-audio endpoint management
     refactoring

   - More enhancements for Cirrus HD-audio codec support (still ongoing)

   - Addition of generic serial MIDI driver"

* tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (504 commits)
  ALSA: hda/realtek - Add new type for ALC245
  ALSA: usb-audio: Configure sync endpoints before data
  ALSA: ctxfi: fix typo in comment
  ALSA: cs5535audio: fix typo in comment
  ALSA: ctxfi: Add SB046x PCI ID
  ALSA: usb-audio: Add missing ep_idx in fixed EP quirks
  ALSA: usb-audio: Workaround for clock setup on TEAC devices
  ALSA: lola: Bounds check loop iterator against streams array size
  ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
  ASoC: rt1308-sdw: add the default value of register 0xc320
  ASoC: rt9120: Use pm_runtime and regcache to optimize 'pwdnn' logic
  ASoC: rt9120: Fix 3byte read, valule offset typo
  ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver.
  ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver
  ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
  ASoC: codecs: lpass: Fix passing zero to 'PTR_ERR'
  ASoC: SOF: sof-client-ipc-flood-test: use pm_runtime_resume_and_get()
  ASoC: SOF: mediatek: remove duplicate include in mt8195.c
  ASoC: SOF: mediatek: Add mt8195 debug dump
  ASoC: SOF: mediatek: Add mediatek common debug dump
  ...
This commit is contained in:
Linus Torvalds 2022-05-25 16:55:16 -07:00
commit d7227785e3
571 changed files with 25863 additions and 9309 deletions

View File

@ -0,0 +1,105 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/dsp/mediatek,mt8195-dsp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek mt8195 DSP core
maintainers:
- YC Hung <yc.hung@mediatek.com>
description: |
Some boards from mt8195 contain a DSP core used for
advanced pre- and post- audio processing.
properties:
compatible:
const: mediatek,mt8195-dsp
reg:
items:
- description: Address and size of the DSP Cfg registers
- description: Address and size of the DSP SRAM
reg-names:
items:
- const: cfg
- const: sram
clocks:
items:
- description: mux for audio dsp clock
- description: 26M clock
- description: mux for audio dsp local bus
- description: default audio dsp local bus clock source
- description: clock gate for audio dsp clock
- description: mux for audio dsp access external bus
clock-names:
items:
- const: adsp_sel
- const: clk26m_ck
- const: audio_local_bus
- const: mainpll_d7_d2
- const: scp_adsp_audiodsp
- const: audio_h
power-domains:
maxItems: 1
mboxes:
items:
- description: ipc reply between host and audio DSP.
- description: ipc request between host and audio DSP.
mbox-names:
items:
- const: mbox0
- const: mbox1
memory-region:
items:
- description: dma buffer between host and DSP.
- description: DSP system memory.
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- memory-region
- power-domains
- mbox-names
- mboxes
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
dsp@10803000 {
compatible = "mediatek,mt8195-dsp";
reg = <0x10803000 0x1000>,
<0x10840000 0x40000>;
reg-names = "cfg", "sram";
clocks = <&topckgen 10>, //CLK_TOP_ADSP
<&clk26m>,
<&topckgen 107>, //CLK_TOP_AUDIO_LOCAL_BUS
<&topckgen 136>, //CLK_TOP_MAINPLL_D7_D2
<&scp_adsp 0>, //CLK_SCP_ADSP_AUDIODSP
<&topckgen 34>; //CLK_TOP_AUDIO_H
clock-names = "adsp_sel",
"clk26m_ck",
"audio_local_bus",
"mainpll_d7_d2",
"scp_adsp_audiodsp",
"audio_h";
memory-region = <&adsp_dma_mem_reserved>,
<&adsp_mem_reserved>;
power-domains = <&spm 6>; //MT8195_POWER_DOMAIN_ADSP
mbox-names = "mbox0", "mbox1";
mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
};

View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/adi,max98396.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices MAX98396 Speaker Amplifier Device Tree Bindings
maintainers:
- Ryan Lee <ryans.lee@analog.com>
description:
The MAX98396 is a mono Class-DG speaker amplifier with I/V sense.
The device provides a PCM interface for audio data and a standard
I2C interface for control data communication.
The MAX98397 is a variant of MAX98396 with wide input supply range.
properties:
compatible:
enum:
- adi,max98396
- adi,max98397
reg:
maxItems: 1
description: I2C address of the device.
adi,vmon-slot-no:
description: slot number of the voltage sense monitor
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 0
adi,imon-slot-no:
description: slot number of the current sense monitor
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 0
adi,spkfb-slot-no:
description: slot number of speaker DSP monitor
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 15
default: 0
adi,interleave-mode:
description:
For cases where a single combined channel for the I/V sense data
is not sufficient, the device can also be configured to share
a single data output channel on alternating frames.
In this configuration, the current and voltage data will be frame
interleaved on a single output channel.
type: boolean
reset-gpios:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
max98396: amplifier@39 {
compatible = "adi,max98396";
reg = <0x39>;
adi,vmon-slot-no = <0>;
adi,imon-slot-no = <1>;
reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
};
};

View File

@ -75,6 +75,19 @@ properties:
maximum: 3
default: 2
cirrus,boost-type:
description:
Configures the type of Boost being used.
Internal boost requires boost-peak-milliamp, boost-ind-nanohenry and
boost-cap-microfarad.
External Boost must have GPIO1 as GPIO output. GPIO1 will be set high to
enable boost voltage.
0 = Internal Boost
1 = External Boost
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 1
cirrus,gpio1-polarity-invert:
description:
Boolean which specifies whether the GPIO1
@ -131,9 +144,32 @@ required:
- compatible
- reg
- "#sound-dai-cells"
- cirrus,boost-peak-milliamp
- cirrus,boost-ind-nanohenry
- cirrus,boost-cap-microfarad
allOf:
- if:
properties:
cirrus,boost-type:
const: 0
then:
required:
- cirrus,boost-peak-milliamp
- cirrus,boost-ind-nanohenry
- cirrus,boost-cap-microfarad
else:
if:
properties:
cirrus,boost-type:
const: 1
then:
required:
- cirrus,gpio1-output-enable
- cirrus,gpio1-src-select
properties:
cirrus,boost-peak-milliamp: false
cirrus,boost-ind-nanohenry: false
cirrus,boost-cap-microfarad: false
cirrus,gpio1-src-select:
enum: [1]
additionalProperties: false
@ -150,6 +186,8 @@ examples:
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 0>;
cirrus,boost-type = <0>;
cirrus,boost-peak-milliamp = <4500>;
cirrus,boost-ind-nanohenry = <1000>;
cirrus,boost-cap-microfarad = <15>;

View File

@ -0,0 +1,75 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/cirrus,cs35l45.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cirrus Logic CS35L45 Speaker Amplifier
maintainers:
- Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
- Richard Fitzgerald <rf@opensource.cirrus.com>
description: |
CS35L45 is a Boosted Mono Class D Amplifier with DSP
Speaker Protection and Adaptive Battery Management.
properties:
compatible:
enum:
- cirrus,cs35l45
reg:
maxItems: 1
'#sound-dai-cells':
const: 1
reset-gpios:
maxItems: 1
vdd-a-supply:
description: voltage regulator phandle for the VDD_A supply
vdd-batt-supply:
description: voltage regulator phandle for the VDD_BATT supply
spi-max-frequency:
maximum: 5000000
cirrus,asp-sdout-hiz-ctrl:
description:
Audio serial port SDOUT Hi-Z control. Sets the Hi-Z
configuration for SDOUT pin of amplifier. Logical OR of
CS35L45_ASP_TX_HIZ_xxx values.
$ref: "/schemas/types.yaml#/definitions/uint32"
minimum: 0
maximum: 3
default: 2
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/cs35l45.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
cs35l45: cs35l45@2 {
#sound-dai-cells = <1>;
compatible = "cirrus,cs35l45";
reg = <2>;
spi-max-frequency = <5000000>;
vdd-a-supply = <&dummy_vreg>;
vdd-batt-supply = <&dummy_vreg>;
reset-gpios = <&gpio 110 0>;
cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED |
CS35L45_ASP_TX_HIZ_DISABLED)>;
};
};

View File

@ -6,6 +6,7 @@ microphone bitstream in a configurable output sampling rate.
Required properties:
- compatible : Compatible list, contains "fsl,imx8mm-micfil"
or "fsl,imx8mp-micfil"
- reg : Offset and length of the register set for the device.

View File

@ -29,6 +29,9 @@ properties:
minimum: 1
maximum: 8388607
reset-gpios:
maxItems: 1
required:
- compatible
- reg
@ -37,6 +40,7 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
@ -45,5 +49,6 @@ examples:
reg = <0x38>;
maxim,temperature_calib = <1024>;
maxim,r0_calib = <100232>;
reset-gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
};
};

View File

@ -18,6 +18,7 @@ properties:
enum:
- mediatek,mt8192_mt6359_rt1015_rt5682
- mediatek,mt8192_mt6359_rt1015p_rt5682
- mediatek,mt8192_mt6359_rt1015p_rt5682s
mediatek,platform:
$ref: "/schemas/types.yaml#/definitions/phandle"
@ -27,11 +28,33 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of HDMI codec.
headset-codec:
type: object
properties:
sound-dai:
$ref: /schemas/types.yaml#/definitions/phandle
required:
- sound-dai
speaker-codecs:
type: object
properties:
sound-dai:
minItems: 1
maxItems: 2
items:
maxItems: 1
$ref: /schemas/types.yaml#/definitions/phandle-array
required:
- sound-dai
additionalProperties: false
required:
- compatible
- mediatek,platform
- headset-codec
- speaker-codecs
examples:
- |
@ -44,6 +67,15 @@ examples:
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
headset-codec {
sound-dai = <&rt5682>;
};
speaker-codecs {
sound-dai = <&rt1015_l>,
<&rt1015_r>;
};
};
...

View File

@ -1,51 +0,0 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1011-rt5682.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek MT8195 with MT6359, RT1011 and RT5682 ASoC sound card driver
maintainers:
- Trevor Wu <trevor.wu@mediatek.com>
description:
This binding describes the MT8195 sound card with RT1011 and RT5682.
properties:
compatible:
const: mediatek,mt8195_mt6359_rt1011_rt5682
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
mediatek,platform:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 ASoC platform.
mediatek,dptx-codec:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 Display Port Tx codec node.
mediatek,hdmi-codec:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8195 HDMI codec node.
additionalProperties: false
required:
- compatible
- mediatek,platform
examples:
- |
sound: mt8195-sound {
compatible = "mediatek,mt8195_mt6359_rt1011_rt5682";
mediatek,platform = <&afe>;
pinctrl-names = "default";
pinctrl-0 = <&aud_pins_default>;
};
...

View File

@ -1,10 +1,10 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
$id: http://devicetree.org/schemas/sound/mt8195-mt6359.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
title: MediaTek MT8195 ASoC sound card driver
maintainers:
- Trevor Wu <trevor.wu@mediatek.com>
@ -14,7 +14,10 @@ description:
properties:
compatible:
const: mediatek,mt8195_mt6359_rt1019_rt5682
enum:
- mediatek,mt8195_mt6359_rt1019_rt5682
- mediatek,mt8195_mt6359_rt1011_rt5682
- mediatek,mt8195_mt6359_max98390_rt5682
model:
$ref: /schemas/types.yaml#/definitions/string

View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra186-asrc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tegra186 ASRC Device Tree Bindings
description: |
Asynchronous Sample Rate Converter (ASRC) converts the sampling frequency
of the input signal from one frequency to another. It can handle over a
wide range of sample rate ratios (freq_in/freq_out) from 1:24 to 24:1.
ASRC has two modes of operation. One where ratio can be programmed in SW
and the other where it gets the information from ratio estimator module.
It supports sample rate conversions in the range of 8 to 192 kHz and
supports 6 streams upto 12 total channels. The input data size can be
16, 24 and 32 bits.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Mohan Kumar <mkumard@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: name-prefix.yaml#
properties:
$nodename:
pattern: "^asrc@[0-9a-f]*$"
compatible:
oneOf:
- const: nvidia,tegra186-asrc
- items:
- enum:
- nvidia,tegra234-asrc
- nvidia,tegra194-asrc
- const: nvidia,tegra186-asrc
reg:
maxItems: 1
sound-name-prefix:
pattern: "^ASRC[1-9]$"
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
ASRC has seven input ports and six output ports. Accordingly ACIF
(Audio Client Interfaces) port nodes are defined to represent the
ASRC inputs (port 0 to 6) and outputs (port 7 to 12). These are
connected to corresponding ports on AHUB (Audio Hub). Additional
input (port 6) is for receiving ratio information from estimator.
patternProperties:
'^port@[0-6]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ASRC ACIF input ports
'^port@[7-9]|1[1-2]':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
description: ASRC ACIF output ports
required:
- compatible
- reg
additionalProperties: false
examples:
- |
asrc@2910000 {
compatible = "nvidia,tegra186-asrc";
reg = <0x2910000 0x2000>;
sound-name-prefix = "ASRC1";
};
...

View File

@ -106,6 +106,10 @@ patternProperties:
type: object
$ref: nvidia,tegra210-mixer.yaml#
'^asrc@[0-9a-f]+$':
type: object
$ref: nvidia,tegra186-asrc.yaml#
required:
- compatible
- reg

View File

@ -38,8 +38,8 @@ properties:
maxItems: 7
clock-names:
minItems: 3
maxItems: 7
minItems: 1
maxItems: 10
interrupts:
minItems: 2
@ -62,6 +62,9 @@ properties:
power-domains:
maxItems: 1
power-domain-names:
maxItems: 1
'#sound-dai-cells':
const: 1
@ -192,15 +195,19 @@ allOf:
oneOf:
- items: #for I2S
- const: aon_cc_audio_hm_h
- const: audio_cc_ext_mclk0
- const: core_cc_sysnoc_mport_core
- const: core_cc_ext_if0_ibit
- const: core_cc_ext_if1_ibit
- items: #for Soundwire
- const: aon_cc_audio_hm_h
- const: audio_cc_codec_mem
- const: audio_cc_codec_mem0
- const: audio_cc_codec_mem1
- const: audio_cc_codec_mem2
- const: aon_cc_va_mem0
- items: #for HDMI
- const: aon_cc_audio_hm_h
- const: core_cc_sysnoc_mport_core
reg-names:
anyOf:
@ -228,6 +235,10 @@ allOf:
- const: lpass-irq-hdmi
- const: lpass-irq-vaif
- const: lpass-irq-rxtxif
power-domain-names:
allOf:
- items:
- const: lcx
required:
- iommus

View File

@ -28,12 +28,17 @@ properties:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
oneOf:
- items: #for ADSP based platforms
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
- items: #for ADSP bypass based platforms
- const: mclk
- const: npl
- const: fsgen
clock-output-names:
items:

View File

@ -28,12 +28,17 @@ properties:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
oneOf:
- items: #for ADSP based platforms
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
- items: #for ADSP bypass based platforms
- const: mclk
- const: npl
- const: fsgen
clock-output-names:
items:

View File

@ -28,10 +28,13 @@ properties:
maxItems: 3
clock-names:
items:
- const: mclk
- const: core
- const: dcodec
oneOf:
- items: #for ADSP based platforms
- const: mclk
- const: core
- const: dcodec
- items: #for ADSP bypass based platforms
- const: mclk
clock-output-names:
items:

View File

@ -36,6 +36,9 @@ properties:
vdd-io-supply:
description: A reference to the 1.8V I/O supply
vdd-mic-bias-supply:
description: A reference to the 3.8V mic bias supply
qcom,tx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire tx device phandle

View File

@ -25,6 +25,9 @@ properties:
0 means shut down; 1 means power on.
maxItems: 1
"#sound-dai-cells":
const: 0
required:
- compatible

View File

@ -46,6 +46,8 @@ Optional properties:
- realtek,dmic-clk-driving-high : Set the high driving of the DMIC clock out.
- #sound-dai-cells: Should be set to '<0>'.
Pins on the device (for linking into audio routes) for RT5682:
* DMIC L1

View File

@ -0,0 +1,51 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/serial-midi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic Serial MIDI Interface
maintainers:
- Daniel Kaehn <kaehndan@gmail.com>
description:
Generic MIDI interface using a serial device. This denotes that a serial device is
dedicated to MIDI communication, either to an external MIDI device through a DIN5
or other connector, or to a known hardwired MIDI controller. This device must be a
child node of a serial node.
Can only be set to use standard baud rates corresponding to supported rates of the
parent serial device. If the standard MIDI baud of 31.25 kBaud is needed
(as would be the case if interfacing with arbitrary external MIDI devices),
configure the clocks of the parent serial device so that a requested baud of 38.4 kBaud
resuts in the standard MIDI baud rate, and set the 'current-speed' property to 38400 (default)
properties:
compatible:
const: serial-midi
current-speed:
description: Baudrate to set the serial port to when this MIDI device is opened.
default: 38400
required:
- compatible
additionalProperties: false
examples:
- |
serial {
midi {
compatible = "serial-midi";
};
};
- |
serial {
midi {
compatible = "serial-midi";
current-speed = <115200>;
};
};

View File

@ -1,25 +1,26 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2020 Texas Instruments Incorporated
# Copyright (C) 2020-2022 Texas Instruments Incorporated
%YAML 1.2
---
$id: "http://devicetree.org/schemas/sound/tas2764.yaml#"
$id: "http://devicetree.org/schemas/sound/tas27xx.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Texas Instruments TAS2764 Smart PA
title: Texas Instruments TAS2764/TAS2780 Smart PA
maintainers:
- Dan Murphy <dmurphy@ti.com>
- Shenghao Ding <shenghao-ding@ti.com>
description: |
The TAS2764 is a mono, digital input Class-D audio amplifier optimized for
efficiently driving high peak power into small loudspeakers.
Integrated speaker voltage and current sense provides for
real time monitoring of loudspeaker behavior.
The TAS2764/TAS2780 is a mono, digital input Class-D audio amplifier
optimized for efficiently driving high peak power into small
loudspeakers. Integrated speaker voltage and current sense provides
for real time monitoring of loudspeaker behavior.
properties:
compatible:
enum:
- ti,tas2764
- ti,tas2780
reg:
maxItems: 1

View File

@ -0,0 +1,97 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/wlf,wm8731.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Wolfson Microelectromics WM8731 audio CODEC
maintainers:
- patches@opensource.cirrus.com
description: |
Wolfson Microelectronics WM8731 audio CODEC
Pins on the device (for linking into audio routes):
* LOUT: Left Channel Line Output
* ROUT: Right Channel Line Output
* LHPOUT: Left Channel Headphone Output
* RHPOUT: Right Channel Headphone Output
* LLINEIN: Left Channel Line Input
* RLINEIN: Right Channel Line Input
* MICIN: Microphone Input
properties:
compatible:
enum:
- wlf,wm8731
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
clocks:
description: Clock provider for MCLK pin.
maxItems: 1
clock-names:
items:
- const: mclk
AVDD-supply:
description: Analog power supply regulator on the AVDD pin.
HPVDD-supply:
description: Headphone power supply regulator on the HPVDD pin.
DBVDD-supply:
description: Digital buffer supply regulator for the DBVDD pin.
DCVDD-supply:
description: Digital core supply regulator for the DCVDD pin.
spi-max-frequency: true
additionalProperties: false
required:
- reg
- compatible
- AVDD-supply
- HPVDD-supply
- DBVDD-supply
- DCVDD-supply
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
wm8731_i2c: codec@0 {
compatible = "wlf,wm8731";
reg = <0>;
spi-max-frequency = <12500000>;
AVDD-supply = <&avdd_reg>;
HPVDD-supply = <&hpvdd_reg>;
DCVDD-supply = <&dcvdd_reg>;
DBVDD-supply = <&dbvdd_reg>;
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
wm8731_spi: codec@1b {
compatible = "wlf,wm8731";
reg = <0x1b>;
AVDD-supply = <&avdd_reg>;
HPVDD-supply = <&hpvdd_reg>;
DCVDD-supply = <&dcvdd_reg>;
DBVDD-supply = <&dbvdd_reg>;
};
};

View File

@ -0,0 +1,57 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/wlf,wm8940.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Wolfson WM8940 Codec Device Tree Bindings
maintainers:
- patches@opensource.cirrus.com
properties:
'#sound-dai-cells':
const: 0
compatible:
const: wlf,wm8940
reg:
maxItems: 1
spi-max-frequency:
maximum: 526000
required:
- '#sound-dai-cells'
- compatible
- reg
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
codec@0 {
#sound-dai-cells = <0>;
compatible = "wlf,wm8940";
reg = <0>;
spi-max-frequency = <500000>;
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
#sound-dai-cells = <0>;
compatible = "wlf,wm8940";
reg = <0x1a>;
};
};
...

View File

@ -1,27 +0,0 @@
WM8731 audio CODEC
This device supports both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible : "wlf,wm8731"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
Example:
wm8731: codec@1a {
compatible = "wlf,wm8731";
reg = <0x1a>;
};
Available audio endpoints for an audio-routing table:
* LOUT: Left Channel Line Output
* ROUT: Right Channel Line Output
* LHPOUT: Left Channel Headphone Output
* RHPOUT: Right Channel Headphone Output
* LLINEIN: Left Channel Line Input
* RLINEIN: Right Channel Line Input
* MICIN: Microphone Input

View File

@ -2246,7 +2246,7 @@ implicit_fb
Apply the generic implicit feedback sync mode. When this is set
and the playback stream sync mode is ASYNC, the driver tries to
tie an adjacent ASYNC capture stream as the implicit feedback
source.
source. This is equivalent with quirk_flags bit 17.
use_vmalloc
Use vmalloc() for allocations of the PCM buffers (default: yes).
For architectures with non-coherent memory like ARM or MIPS, the
@ -2288,6 +2288,8 @@ quirk_flags
* bit 14: Ignore errors for mixer access
* bit 15: Support generic DSD raw U32_BE format
* bit 16: Set up the interface at first like UAC1
* bit 17: Apply the generic implicit feedback sync mode
* bit 18: Don't apply implicit feedback sync mode
This module supports multiple devices, autoprobe and hotplugging.

View File

@ -4705,10 +4705,12 @@ CIRRUS LOGIC AUDIO CODEC DRIVERS
M: James Schulman <james.schulman@cirrus.com>
M: David Rhodes <david.rhodes@cirrus.com>
M: Lucas Tanure <tanureal@opensource.cirrus.com>
M: Richard Fitzgerald <rf@opensource.cirrus.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: patches@opensource.cirrus.com
S: Maintained
F: Documentation/devicetree/bindings/sound/cirrus,cs*
F: include/dt-bindings/sound/cs*
F: sound/pci/hda/cs*
F: sound/soc/codecs/cs*

View File

@ -211,7 +211,8 @@ CONFIG_SND_ATMEL_SOC_WM8904=m
CONFIG_SND_AT91_SOC_SAM9X5_WM8731=m
CONFIG_SND_KIRKWOOD_SOC=y
CONFIG_SND_SOC_ALC5623=y
CONFIG_SND_SOC_WM8731=y
CONFIG_SND_SOC_WM8731_I2C=y
CONFIG_SND_SOC_WM8731_SPI=y
CONFIG_SND_SIMPLE_CARD=y
CONFIG_HID_DRAGONRISE=y
CONFIG_HID_GYRATION=y

View File

@ -25,7 +25,7 @@
#include <linux/of_dma.h>
#include <asm/irq.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#include "dmaengine.h"
#define IMXDMA_MAX_CHAN_DESCRIPTORS 16

View File

@ -14,6 +14,7 @@
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@ -35,7 +36,7 @@
#include <linux/workqueue.h>
#include <asm/irq.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@ -73,6 +74,7 @@
#define SDMA_CHNENBL0_IMX35 0x200
#define SDMA_CHNENBL0_IMX31 0x080
#define SDMA_CHNPRI_0 0x100
#define SDMA_DONE0_CONFIG 0x1000
/*
* Buffer descriptor status values.
@ -180,6 +182,12 @@
BIT(DMA_MEM_TO_DEV) | \
BIT(DMA_DEV_TO_DEV))
#define SDMA_WATERMARK_LEVEL_N_FIFOS GENMASK(15, 12)
#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23)
#define SDMA_DONE0_CONFIG_DONE_SEL BIT(7)
#define SDMA_DONE0_CONFIG_DONE_DIS BIT(6)
/**
* struct sdma_script_start_addrs - SDMA script start pointers
*
@ -441,6 +449,9 @@ struct sdma_channel {
struct work_struct terminate_worker;
struct list_head terminated;
bool is_ram_script;
unsigned int n_fifos_src;
unsigned int n_fifos_dst;
bool sw_done;
};
#define IMX_DMA_SG_LOOP BIT(0)
@ -778,6 +789,14 @@ static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event)
val = readl_relaxed(sdma->regs + chnenbl);
__set_bit(channel, &val);
writel_relaxed(val, sdma->regs + chnenbl);
/* Set SDMA_DONEx_CONFIG is sw_done enabled */
if (sdmac->sw_done) {
val = readl_relaxed(sdma->regs + SDMA_DONE0_CONFIG);
val |= SDMA_DONE0_CONFIG_DONE_SEL;
val &= ~SDMA_DONE0_CONFIG_DONE_DIS;
writel_relaxed(val, sdma->regs + SDMA_DONE0_CONFIG);
}
}
static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
@ -940,7 +959,7 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
/*
* sets the pc of SDMA script according to the peripheral type
*/
static void sdma_get_pc(struct sdma_channel *sdmac,
static int sdma_get_pc(struct sdma_channel *sdmac,
enum sdma_peripheral_type peripheral_type)
{
struct sdma_engine *sdma = sdmac->sdma;
@ -1038,14 +1057,22 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
case IMX_DMATYPE_IPU_MEMORY:
emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr;
break;
default:
case IMX_DMATYPE_MULTI_SAI:
per_2_emi = sdma->script_addrs->sai_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_sai_addr;
break;
default:
dev_err(sdma->dev, "Unsupported transfer type %d\n",
peripheral_type);
return -EINVAL;
}
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
sdmac->device_to_device = per_2_per;
sdmac->pc_to_pc = emi_2_emi;
return 0;
}
static int sdma_load_context(struct sdma_channel *sdmac)
@ -1210,9 +1237,26 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT;
}
static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac)
{
unsigned int n_fifos;
if (sdmac->sw_done)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE;
if (sdmac->direction == DMA_DEV_TO_MEM)
n_fifos = sdmac->n_fifos_src;
else
n_fifos = sdmac->n_fifos_dst;
sdmac->watermark_level |=
FIELD_PREP(SDMA_WATERMARK_LEVEL_N_FIFOS, n_fifos);
}
static int sdma_config_channel(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
int ret;
sdma_disable_channel(chan);
@ -1233,7 +1277,9 @@ static int sdma_config_channel(struct dma_chan *chan)
break;
}
sdma_get_pc(sdmac, sdmac->peripheral_type);
ret = sdma_get_pc(sdmac, sdmac->peripheral_type);
if (ret)
return ret;
if ((sdmac->peripheral_type != IMX_DMATYPE_MEMORY) &&
(sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
@ -1243,6 +1289,10 @@ static int sdma_config_channel(struct dma_chan *chan)
sdmac->peripheral_type == IMX_DMATYPE_ASRC)
sdma_set_watermarklevel_for_p2p(sdmac);
} else {
if (sdmac->peripheral_type ==
IMX_DMATYPE_MULTI_SAI)
sdma_set_watermarklevel_for_sais(sdmac);
__set_bit(sdmac->event_id0, sdmac->event_mask);
}
@ -1349,7 +1399,9 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
mem_data.dma_request2 = 0;
data = &mem_data;
sdma_get_pc(sdmac, IMX_DMATYPE_MEMORY);
ret = sdma_get_pc(sdmac, IMX_DMATYPE_MEMORY);
if (ret)
return ret;
}
switch (data->priority) {
@ -1698,9 +1750,23 @@ static int sdma_config(struct dma_chan *chan,
struct dma_slave_config *dmaengine_cfg)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
if (dmaengine_cfg->peripheral_config) {
struct sdma_peripheral_config *sdmacfg = dmaengine_cfg->peripheral_config;
if (dmaengine_cfg->peripheral_size != sizeof(struct sdma_peripheral_config)) {
dev_err(sdma->dev, "Invalid peripheral size %zu, expected %zu\n",
dmaengine_cfg->peripheral_size,
sizeof(struct sdma_peripheral_config));
return -EINVAL;
}
sdmac->n_fifos_src = sdmacfg->n_fifos_src;
sdmac->n_fifos_dst = sdmacfg->n_fifos_dst;
sdmac->sw_done = sdmacfg->sw_done;
}
/* Set ENBLn earlier to make sure dma request triggered after that */
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
return -EINVAL;

View File

@ -616,6 +616,15 @@ static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card,
return ERR_PTR(-ENODEV);
}
static u32 dummy_read_csr(struct fw_card *card, int csr_offset)
{
return 0;
}
static void dummy_write_csr(struct fw_card *card, int csr_offset, u32 value)
{
}
static int dummy_start_iso(struct fw_iso_context *ctx,
s32 cycle, u32 sync, u32 tags)
{
@ -649,6 +658,8 @@ static const struct fw_card_driver dummy_driver_template = {
.send_response = dummy_send_response,
.cancel_packet = dummy_cancel_packet,
.enable_phys_dma = dummy_enable_phys_dma,
.read_csr = dummy_read_csr,
.write_csr = dummy_write_csr,
.allocate_iso_context = dummy_allocate_iso_context,
.start_iso = dummy_start_iso,
.set_iso_channels = dummy_set_iso_channels,
@ -694,3 +705,31 @@ void fw_core_remove_card(struct fw_card *card)
WARN_ON(!list_empty(&card->transaction_list));
}
EXPORT_SYMBOL(fw_core_remove_card);
/**
* fw_card_read_cycle_time: read from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region
* for controller card.
* @card: The instance of card for 1394 OHCI controller.
* @cycle_time: The mutual reference to value of cycle time for the read operation.
*
* Read value from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region for the given
* controller card. This function accesses the region without any lock primitives or IRQ mask.
* When returning successfully, the content of @value argument has value aligned to host endianness,
* formetted by CYCLE_TIME CSR Register of IEEE 1394 std.
*
* Context: Any context.
* Return:
* * 0 - Read successfully.
* * -ENODEV - The controller is unavailable due to being removed or unbound.
*/
int fw_card_read_cycle_time(struct fw_card *card, u32 *cycle_time)
{
if (card->driver->read_csr == dummy_read_csr)
return -ENODEV;
// It's possible to switch to dummy driver between the above and the below. This is the best
// effort to return -ENODEV.
*cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
return 0;
}
EXPORT_SYMBOL_GPL(fw_card_read_cycle_time);

View File

@ -1216,7 +1216,9 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
local_irq_disable();
cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
ret = fw_card_read_cycle_time(card, &cycle_time);
if (ret < 0)
goto end;
switch (a->clk_id) {
case CLOCK_REALTIME: ktime_get_real_ts64(&ts); break;
@ -1225,7 +1227,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
default:
ret = -EINVAL;
}
end:
local_irq_enable();
a->tv_sec = ts.tv_sec;

View File

@ -620,6 +620,7 @@ struct fw_request {
struct fw_packet response;
u32 request_header[4];
int ack;
u32 timestamp;
u32 length;
u32 data[];
};
@ -789,6 +790,7 @@ static struct fw_request *allocate_request(struct fw_card *card,
request->response.ack = 0;
request->response.callback = free_response_callback;
request->ack = p->ack;
request->timestamp = p->timestamp;
request->length = length;
if (data)
memcpy(request->data, data, length);
@ -833,6 +835,22 @@ int fw_get_request_speed(struct fw_request *request)
}
EXPORT_SYMBOL(fw_get_request_speed);
/**
* fw_request_get_timestamp: Get timestamp of the request.
* @request: The opaque pointer to request structure.
*
* Get timestamp when 1394 OHCI controller receives the asynchronous request subaction. The
* timestamp consists of the low order 3 bits of second field and the full 13 bits of count
* field of isochronous cycle time register.
*
* Returns: timestamp of the request.
*/
u32 fw_request_get_timestamp(const struct fw_request *request)
{
return request->timestamp;
}
EXPORT_SYMBOL_GPL(fw_request_get_timestamp);
static void handle_exclusive_region_request(struct fw_card *card,
struct fw_packet *p,
struct fw_request *request,

View File

@ -203,6 +203,15 @@ config INTEL_STRATIX10_RSU
Say Y here if you want Intel RSU support.
config MTK_ADSP_IPC
tristate "MTK ADSP IPC Protocol driver"
depends on MTK_ADSP_MBOX
help
Say yes here to add support for the MediaTek ADSP IPC
between host AP (Linux) and the firmware running on ADSP.
ADSP exists on some mtk processors.
Client might use shared memory to exchange information with ADSP.
config QCOM_SCM
tristate

View File

@ -15,6 +15,7 @@ obj-$(CONFIG_INTEL_STRATIX10_RSU) += stratix10-rsu.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_MTK_ADSP_IPC) += mtk-adsp-ipc.o
obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o

View File

@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2022 MediaTek Corporation. All rights reserved.
* Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com>
*/
#include <linux/firmware/mediatek/mtk-adsp-ipc.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
/*
* mtk_adsp_ipc_send - send ipc cmd to MTK ADSP
*
* @ipc: ADSP IPC handle
* @idx: index of the mailbox channel
* @msg: IPC cmd (reply or request)
*
* Returns zero for success from mbox_send_message
* negative value for error
*/
int mtk_adsp_ipc_send(struct mtk_adsp_ipc *ipc, unsigned int idx, uint32_t msg)
{
struct mtk_adsp_chan *adsp_chan;
int ret;
if (idx >= MTK_ADSP_MBOX_NUM)
return -EINVAL;
adsp_chan = &ipc->chans[idx];
ret = mbox_send_message(adsp_chan->ch, &msg);
if (ret < 0)
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(mtk_adsp_ipc_send);
/*
* mtk_adsp_ipc_recv - recv callback used by MTK ADSP mailbox
*
* @c: mbox client
* @msg: message received
*
* Users of ADSP IPC will need to privde handle_reply and handle_request
* callbacks.
*/
static void mtk_adsp_ipc_recv(struct mbox_client *c, void *msg)
{
struct mtk_adsp_chan *chan = container_of(c, struct mtk_adsp_chan, cl);
struct device *dev = c->dev;
switch (chan->idx) {
case MTK_ADSP_MBOX_REPLY:
chan->ipc->ops->handle_reply(chan->ipc);
break;
case MTK_ADSP_MBOX_REQUEST:
chan->ipc->ops->handle_request(chan->ipc);
break;
default:
dev_err(dev, "wrong mbox chan %d\n", chan->idx);
break;
}
}
static int mtk_adsp_ipc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_adsp_ipc *adsp_ipc;
struct mtk_adsp_chan *adsp_chan;
struct mbox_client *cl;
char *chan_name;
int ret;
int i, j;
device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
adsp_ipc = devm_kzalloc(dev, sizeof(*adsp_ipc), GFP_KERNEL);
if (!adsp_ipc)
return -ENOMEM;
for (i = 0; i < MTK_ADSP_MBOX_NUM; i++) {
chan_name = kasprintf(GFP_KERNEL, "mbox%d", i);
if (!chan_name) {
ret = -ENOMEM;
goto out;
}
adsp_chan = &adsp_ipc->chans[i];
cl = &adsp_chan->cl;
cl->dev = dev->parent;
cl->tx_block = false;
cl->knows_txdone = false;
cl->tx_prepare = NULL;
cl->rx_callback = mtk_adsp_ipc_recv;
adsp_chan->ipc = adsp_ipc;
adsp_chan->idx = i;
adsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
if (IS_ERR(adsp_chan->ch)) {
ret = PTR_ERR(adsp_chan->ch);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to request mbox chan %d ret %d\n",
i, ret);
goto out_free;
}
dev_dbg(dev, "request mbox chan %s\n", chan_name);
kfree(chan_name);
}
adsp_ipc->dev = dev;
dev_set_drvdata(dev, adsp_ipc);
dev_dbg(dev, "MTK ADSP IPC initialized\n");
return 0;
out_free:
kfree(chan_name);
out:
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
mbox_free_channel(adsp_chan->ch);
}
return ret;
}
static int mtk_adsp_ipc_remove(struct platform_device *pdev)
{
struct mtk_adsp_ipc *adsp_ipc = dev_get_drvdata(&pdev->dev);
struct mtk_adsp_chan *adsp_chan;
int i;
for (i = 0; i < MTK_ADSP_MBOX_NUM; i++) {
adsp_chan = &adsp_ipc->chans[i];
mbox_free_channel(adsp_chan->ch);
}
return 0;
}
static struct platform_driver mtk_adsp_ipc_driver = {
.driver = {
.name = "mtk-adsp-ipc",
},
.probe = mtk_adsp_ipc_probe,
.remove = mtk_adsp_ipc_remove,
};
builtin_platform_driver(mtk_adsp_ipc_driver);
MODULE_AUTHOR("Allen-KH Cheng <allen-kh.cheng@mediatek.com>");
MODULE_DESCRIPTION("MTK ADSP IPC Driver");
MODULE_LICENSE("GPL");

View File

@ -39,7 +39,7 @@
#include <asm/irq.h>
#include <linux/platform_data/mmc-mxcmmc.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#define DRIVER_NAME "mxc-mmc"
#define MXCMCI_TIMEOUT_MS 10000

View File

@ -20,7 +20,7 @@
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>

View File

@ -23,7 +23,7 @@
#include <linux/of_device.h>
#include <linux/property.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#define DRIVER_NAME "spi_imx"

View File

@ -702,8 +702,9 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module,
headset->pin = module->jack_name;
headset->mask = module->jack_mask;
ret = snd_soc_card_jack_new(card, module->jack_name, module->jack_mask,
&module->headset.jack, headset, 1);
ret = snd_soc_card_jack_new_pins(card, module->jack_name,
module->jack_mask,
&module->headset.jack, headset, 1);
if (ret) {
dev_err(module->dev, "Failed to create new jack\n");
return ret;
@ -725,9 +726,10 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module,
button->pin = module->button_name;
button->mask = module->button_mask;
ret = snd_soc_card_jack_new(card, module->button_name,
module->button_mask, &module->button.jack,
button, 1);
ret = snd_soc_card_jack_new_pins(card, module->button_name,
module->button_mask,
&module->button.jack,
button, 1);
if (ret) {
dev_err(module->dev, "Failed to create button jack\n");
goto free_jacks;

View File

@ -30,7 +30,7 @@
#include <linux/dma-mapping.h>
#include <asm/irq.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#include "serial_mctrl_gpio.h"

View File

@ -26,7 +26,7 @@
#include <linux/dma/ipu-dma.h>
#include <linux/backlight.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/dma/imx-dma.h>
#include <linux/platform_data/video-mx3fb.h>
#include <asm/io.h>

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* cs35l45.h -- CS35L45 ALSA SoC audio driver DT bindings header
*
* Copyright 2022 Cirrus Logic, Inc.
*/
#ifndef DT_CS35L45_H
#define DT_CS35L45_H
/*
* cirrus,asp-sdout-hiz-ctrl
*
* TX_HIZ_UNUSED: TX pin high-impedance during unused slots.
* TX_HIZ_DISABLED: TX pin high-impedance when all channels disabled.
*/
#define CS35L45_ASP_TX_HIZ_UNUSED 0x1
#define CS35L45_ASP_TX_HIZ_DISABLED 0x2
#endif /* DT_CS35L45_H */

View File

@ -3,8 +3,8 @@
* Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
#ifndef __ASM_ARCH_MXC_DMA_H__
#define __ASM_ARCH_MXC_DMA_H__
#ifndef __LINUX_DMA_IMX_H
#define __LINUX_DMA_IMX_H
#include <linux/scatterlist.h>
#include <linux/device.h>
@ -39,6 +39,7 @@ enum sdma_peripheral_type {
IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */
IMX_DMATYPE_ASRC_SP, /* Shared ASRC */
IMX_DMATYPE_SAI, /* SAI */
IMX_DMATYPE_MULTI_SAI, /* MULTI FIFOs For Audio */
};
enum imx_dma_prio {
@ -65,4 +66,23 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
!strcmp(chan->device->dev->driver->name, "imx-dma");
}
#endif
/**
* struct sdma_peripheral_config - SDMA config for audio
* @n_fifos_src: Number of FIFOs for recording
* @n_fifos_dst: Number of FIFOs for playback
* @sw_done: Use software done. Needed for PDM (micfil)
*
* Some i.MX Audio devices (SAI, micfil) have multiple successive FIFO
* registers. For multichannel recording/playback the SAI/micfil have
* one FIFO register per channel and the SDMA engine has to read/write
* the next channel from/to the next register and wrap around to the
* first register when all channels are handled. The number of active
* channels must be communicated to the SDMA engine using this struct.
*/
struct sdma_peripheral_config {
int n_fifos_src;
int n_fifos_dst;
bool sw_done;
};
#endif /* __LINUX_DMA_IMX_H */

View File

@ -150,6 +150,8 @@ static inline void fw_card_put(struct fw_card *card)
kref_put(&card->kref, fw_card_release);
}
int fw_card_read_cycle_time(struct fw_card *card, u32 *cycle_time);
struct fw_attribute_group {
struct attribute_group *groups[2];
struct attribute_group group;
@ -352,6 +354,7 @@ void fw_core_remove_address_handler(struct fw_address_handler *handler);
void fw_send_response(struct fw_card *card,
struct fw_request *request, int rcode);
int fw_get_request_speed(struct fw_request *request);
u32 fw_request_get_timestamp(const struct fw_request *request);
void fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int destination_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length,

View File

@ -68,36 +68,36 @@ struct cs_dsp_alg_region {
/**
* struct cs_dsp_coeff_ctl - Describes a coefficient control
* @list: List node for internal use
* @dsp: DSP instance associated with this control
* @cache: Cached value of the control
* @fw_name: Name of the firmware
* @subname: Name of the control parsed from the WMFW
* @subname_len: Length of subname
* @alg_region: Logical region associated with this control
* @dsp: DSP instance associated with this control
* @enabled: Flag indicating whether control is enabled
* @list: List node for internal use
* @cache: Cached value of the control
* @offset: Offset of control within alg_region in words
* @len: Length of the cached value in bytes
* @set: Flag indicating the value has been written by the user
* @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
* @type: One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
* @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
* @set: Flag indicating the value has been written by the user
* @enabled: Flag indicating whether control is enabled
* @alg_region: Logical region associated with this control
* @priv: For use by the client
*/
struct cs_dsp_coeff_ctl {
struct list_head list;
struct cs_dsp *dsp;
void *cache;
const char *fw_name;
/* Subname is needed to match with firmware */
const char *subname;
unsigned int subname_len;
struct cs_dsp_alg_region alg_region;
struct cs_dsp *dsp;
unsigned int enabled:1;
struct list_head list;
void *cache;
unsigned int offset;
size_t len;
unsigned int set:1;
unsigned int flags;
unsigned int type;
unsigned int flags;
unsigned int set:1;
unsigned int enabled:1;
struct cs_dsp_alg_region alg_region;
void *priv;
};

View File

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2022 MediaTek Inc.
*/
#ifndef MTK_ADSP_IPC_H
#define MTK_ADSP_IPC_H
#include <linux/device.h>
#include <linux/types.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>
#define MTK_ADSP_IPC_REQ 0
#define MTK_ADSP_IPC_RSP 1
#define MTK_ADSP_IPC_OP_REQ 0x1
#define MTK_ADSP_IPC_OP_RSP 0x2
enum {
MTK_ADSP_MBOX_REPLY,
MTK_ADSP_MBOX_REQUEST,
MTK_ADSP_MBOX_NUM,
};
struct mtk_adsp_ipc;
struct mtk_adsp_ipc_ops {
void (*handle_reply)(struct mtk_adsp_ipc *ipc);
void (*handle_request)(struct mtk_adsp_ipc *ipc);
};
struct mtk_adsp_chan {
struct mtk_adsp_ipc *ipc;
struct mbox_client cl;
struct mbox_chan *ch;
char *name;
int idx;
};
struct mtk_adsp_ipc {
struct mtk_adsp_chan chans[MTK_ADSP_MBOX_NUM];
struct device *dev;
struct mtk_adsp_ipc_ops *ops;
void *private_data;
};
static inline void mtk_adsp_ipc_set_data(struct mtk_adsp_ipc *ipc, void *data)
{
if (!ipc)
return;
ipc->private_data = data;
}
static inline void *mtk_adsp_ipc_get_data(struct mtk_adsp_ipc *ipc)
{
if (!ipc)
return NULL;
return ipc->private_data;
}
int mtk_adsp_ipc_send(struct mtk_adsp_ipc *ipc, unsigned int idx, uint32_t op);
#endif /* MTK_ADSP_IPC_H */

View File

@ -11,6 +11,7 @@
#define __CS35L41_H
#include <linux/regmap.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#define CS35L41_FIRSTREG 0x00000000
#define CS35L41_LASTREG 0x03804FE8
@ -536,9 +537,7 @@
#define CS35L41_MAX_CACHE_REG 36
#define CS35L41_OTP_SIZE_WORDS 32
#define CS35L41_NUM_OTP_ELEM 100
#define CS35L41_VALID_PDATA 0x80000000
#define CS35L41_NUM_SUPPLIES 2
#define CS35L41_SCLK_MSTR_MASK 0x10
@ -662,6 +661,7 @@
#define CS35L41_GLOBAL_EN_SHIFT 0
#define CS35L41_BST_EN_MASK 0x0030
#define CS35L41_BST_EN_SHIFT 4
#define CS35L41_BST_DIS_FET_OFF 0x00
#define CS35L41_BST_EN_DEFAULT 0x2
#define CS35L41_AMP_EN_SHIFT 0
#define CS35L41_AMP_EN_MASK 1
@ -691,6 +691,13 @@
#define CS35L41_TEMP_WARN_ERR_RLS 0x20
#define CS35L41_TEMP_ERR_RLS 0x40
#define CS35L41_AMP_SHORT_ERR_RLS_SHIFT 1
#define CS35L41_BST_SHORT_ERR_RLS_SHIFT 2
#define CS35L41_BST_OVP_ERR_RLS_SHIFT 3
#define CS35L41_BST_UVP_ERR_RLS_SHIFT 4
#define CS35L41_TEMP_WARN_ERR_RLS_SHIFT 5
#define CS35L41_TEMP_ERR_RLS_SHIFT 6
#define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F
#define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF
#define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF
@ -701,9 +708,8 @@
#define CS35L41_GPIO1_CTRL_SHIFT 16
#define CS35L41_GPIO2_CTRL_MASK 0x07000000
#define CS35L41_GPIO2_CTRL_SHIFT 24
#define CS35L41_GPIO_CTRL_OPEN_INT 2
#define CS35L41_GPIO_CTRL_ACTV_LO 4
#define CS35L41_GPIO_CTRL_ACTV_HI 5
#define CS35L41_GPIO_LVL_SHIFT 15
#define CS35L41_GPIO_LVL_MASK BIT(CS35L41_GPIO_LVL_SHIFT)
#define CS35L41_GPIO_POL_MASK 0x1000
#define CS35L41_GPIO_POL_SHIFT 12
@ -729,25 +735,56 @@
#define CS35L41_SPI_MAX_FREQ 4000000
#define CS35L41_REGSTRIDE 4
enum cs35l41_boost_type {
CS35L41_INT_BOOST,
CS35L41_EXT_BOOST,
CS35L41_EXT_BOOST_NO_VSPK_SWITCH,
};
enum cs35l41_clk_ids {
CS35L41_CLKID_SCLK = 0,
CS35L41_CLKID_LRCLK = 1,
CS35L41_CLKID_MCLK = 4,
};
struct cs35l41_irq_cfg {
bool irq_pol_inv;
bool irq_out_en;
int irq_src_sel;
enum cs35l41_gpio1_func {
CS35L41_GPIO1_HIZ,
CS35L41_GPIO1_GPIO,
CS35L41_GPIO1_MDSYNC,
CS35L41_GPIO1_MCLK,
CS35L41_GPIO1_PDM_CLK,
CS35L41_GPIO1_PDM_DATA,
};
struct cs35l41_platform_data {
enum cs35l41_gpio2_func {
CS35L41_GPIO2_HIZ,
CS35L41_GPIO2_GPIO,
CS35L41_GPIO2_INT_OPEN_DRAIN,
CS35L41_GPIO2_MCLK,
CS35L41_GPIO2_INT_PUSH_PULL_LOW,
CS35L41_GPIO2_INT_PUSH_PULL_HIGH,
CS35L41_GPIO2_PDM_CLK,
CS35L41_GPIO2_PDM_DATA,
};
struct cs35l41_gpio_cfg {
bool valid;
bool pol_inv;
bool out_en;
unsigned int func;
};
struct cs35l41_hw_cfg {
bool valid;
int bst_ind;
int bst_ipk;
int bst_cap;
int dout_hiz;
struct cs35l41_irq_cfg irq_config1;
struct cs35l41_irq_cfg irq_config2;
struct cs35l41_gpio_cfg gpio1;
struct cs35l41_gpio_cfg gpio2;
unsigned int spk_pos;
enum cs35l41_boost_type bst_type;
};
struct cs35l41_otp_packed_element_t {
@ -764,6 +801,71 @@ struct cs35l41_otp_map_element_t {
u32 word_offset;
};
enum cs35l41_cspl_mbox_status {
CSPL_MBOX_STS_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
};
enum cs35l41_cspl_mbox_cmd {
CSPL_MBOX_CMD_NONE = 0,
CSPL_MBOX_CMD_PAUSE = 1,
CSPL_MBOX_CMD_RESUME = 2,
CSPL_MBOX_CMD_REINIT = 3,
CSPL_MBOX_CMD_STOP_PRE_REINIT = 4,
CSPL_MBOX_CMD_HIBERNATE = 5,
CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6,
CSPL_MBOX_CMD_UNKNOWN_CMD = -1,
CSPL_MBOX_CMD_INVALID_SEQUENCE = -2,
};
/*
* IRQs
*/
#define CS35L41_IRQ(_irq, _name, _hand) \
{ \
.irq = CS35L41_ ## _irq ## _IRQ,\
.name = _name, \
.handler = _hand, \
}
struct cs35l41_irq {
int irq;
const char *name;
irqreturn_t (*handler)(int irq, void *data);
};
#define CS35L41_REG_IRQ(_reg, _irq) \
[CS35L41_ ## _irq ## _IRQ] = { \
.reg_offset = (CS35L41_ ## _reg) - CS35L41_IRQ1_STATUS1,\
.mask = CS35L41_ ## _irq ## _MASK \
}
/* (0x0000E010) CS35L41_IRQ1_STATUS1 */
#define CS35L41_BST_OVP_ERR_SHIFT 6
#define CS35L41_BST_OVP_ERR_MASK BIT(CS35L41_BST_OVP_ERR_SHIFT)
#define CS35L41_BST_DCM_UVP_ERR_SHIFT 7
#define CS35L41_BST_DCM_UVP_ERR_MASK BIT(CS35L41_BST_DCM_UVP_ERR_SHIFT)
#define CS35L41_BST_SHORT_ERR_SHIFT 8
#define CS35L41_BST_SHORT_ERR_MASK BIT(CS35L41_BST_SHORT_ERR_SHIFT)
#define CS35L41_TEMP_WARN_SHIFT 15
#define CS35L41_TEMP_WARN_MASK BIT(CS35L41_TEMP_WARN_SHIFT)
#define CS35L41_TEMP_ERR_SHIFT 17
#define CS35L41_TEMP_ERR_MASK BIT(CS35L41_TEMP_ERR_SHIFT)
#define CS35L41_AMP_SHORT_ERR_SHIFT 31
#define CS35L41_AMP_SHORT_ERR_MASK BIT(CS35L41_AMP_SHORT_ERR_SHIFT)
enum cs35l41_irq_list {
CS35L41_BST_OVP_ERR_IRQ,
CS35L41_BST_DCM_UVP_ERR_IRQ,
CS35L41_BST_SHORT_ERR_IRQ,
CS35L41_TEMP_WARN_IRQ,
CS35L41_TEMP_ERR_IRQ,
CS35L41_AMP_SHORT_ERR_IRQ,
CS35L41_NUM_IRQ
};
extern struct regmap_config cs35l41_regmap_i2c;
extern struct regmap_config cs35l41_regmap_spi;
@ -774,7 +876,14 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
int cs35l41_set_channels(struct device *dev, struct regmap *reg,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot);
int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
int boost_ipk);
int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg);
void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp);
int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
enum cs35l41_cspl_mbox_cmd cmd);
int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap);
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
struct cs35l41_hw_cfg *hw_cfg);
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);
int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable);
#endif /* __CS35L41_H */

810
include/sound/cs42l42.h Normal file
View File

@ -0,0 +1,810 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/sound/cs42l42.h -- Platform data for CS42L42 ALSA SoC audio driver header
*
* Copyright 2016-2022 Cirrus Logic, Inc.
*
* Author: James Schulman <james.schulman@cirrus.com>
* Author: Brian Austin <brian.austin@cirrus.com>
* Author: Michael White <michael.white@cirrus.com>
*/
#ifndef __CS42L42_H
#define __CS42L42_H
#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */
#define CS42L42_WIN_START 0x00
#define CS42L42_WIN_LEN 0x100
#define CS42L42_RANGE_MIN 0x00
#define CS42L42_RANGE_MAX 0x7F
#define CS42L42_PAGE_10 0x1000
#define CS42L42_PAGE_11 0x1100
#define CS42L42_PAGE_12 0x1200
#define CS42L42_PAGE_13 0x1300
#define CS42L42_PAGE_15 0x1500
#define CS42L42_PAGE_19 0x1900
#define CS42L42_PAGE_1B 0x1B00
#define CS42L42_PAGE_1C 0x1C00
#define CS42L42_PAGE_1D 0x1D00
#define CS42L42_PAGE_1F 0x1F00
#define CS42L42_PAGE_20 0x2000
#define CS42L42_PAGE_21 0x2100
#define CS42L42_PAGE_23 0x2300
#define CS42L42_PAGE_24 0x2400
#define CS42L42_PAGE_25 0x2500
#define CS42L42_PAGE_26 0x2600
#define CS42L42_PAGE_28 0x2800
#define CS42L42_PAGE_29 0x2900
#define CS42L42_PAGE_2A 0x2A00
#define CS42L42_PAGE_30 0x3000
#define CS42L42_CHIP_ID 0x42A42
/* Page 0x10 Global Registers */
#define CS42L42_DEVID_AB (CS42L42_PAGE_10 + 0x01)
#define CS42L42_DEVID_CD (CS42L42_PAGE_10 + 0x02)
#define CS42L42_DEVID_E (CS42L42_PAGE_10 + 0x03)
#define CS42L42_FABID (CS42L42_PAGE_10 + 0x04)
#define CS42L42_REVID (CS42L42_PAGE_10 + 0x05)
#define CS42L42_FRZ_CTL (CS42L42_PAGE_10 + 0x06)
#define CS42L42_SRC_CTL (CS42L42_PAGE_10 + 0x07)
#define CS42L42_SRC_BYPASS_DAC_SHIFT 1
#define CS42L42_SRC_BYPASS_DAC_MASK (1 << CS42L42_SRC_BYPASS_DAC_SHIFT)
#define CS42L42_MCLK_STATUS (CS42L42_PAGE_10 + 0x08)
#define CS42L42_MCLK_CTL (CS42L42_PAGE_10 + 0x09)
#define CS42L42_INTERNAL_FS_SHIFT 1
#define CS42L42_INTERNAL_FS_MASK (1 << CS42L42_INTERNAL_FS_SHIFT)
#define CS42L42_SFTRAMP_RATE (CS42L42_PAGE_10 + 0x0A)
#define CS42L42_SLOW_START_ENABLE (CS42L42_PAGE_10 + 0x0B)
#define CS42L42_SLOW_START_EN_MASK GENMASK(6, 4)
#define CS42L42_SLOW_START_EN_SHIFT 4
#define CS42L42_I2C_DEBOUNCE (CS42L42_PAGE_10 + 0x0E)
#define CS42L42_I2C_STRETCH (CS42L42_PAGE_10 + 0x0F)
#define CS42L42_I2C_TIMEOUT (CS42L42_PAGE_10 + 0x10)
/* Page 0x11 Power and Headset Detect Registers */
#define CS42L42_PWR_CTL1 (CS42L42_PAGE_11 + 0x01)
#define CS42L42_ASP_DAO_PDN_SHIFT 7
#define CS42L42_ASP_DAO_PDN_MASK (1 << CS42L42_ASP_DAO_PDN_SHIFT)
#define CS42L42_ASP_DAI_PDN_SHIFT 6
#define CS42L42_ASP_DAI_PDN_MASK (1 << CS42L42_ASP_DAI_PDN_SHIFT)
#define CS42L42_MIXER_PDN_SHIFT 5
#define CS42L42_MIXER_PDN_MASK (1 << CS42L42_MIXER_PDN_SHIFT)
#define CS42L42_EQ_PDN_SHIFT 4
#define CS42L42_EQ_PDN_MASK (1 << CS42L42_EQ_PDN_SHIFT)
#define CS42L42_HP_PDN_SHIFT 3
#define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
#define CS42L42_ADC_PDN_SHIFT 2
#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT)
#define CS42L42_PDN_ALL_SHIFT 0
#define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT)
#define CS42L42_PWR_CTL2 (CS42L42_PAGE_11 + 0x02)
#define CS42L42_ADC_SRC_PDNB_SHIFT 0
#define CS42L42_ADC_SRC_PDNB_MASK (1 << CS42L42_ADC_SRC_PDNB_SHIFT)
#define CS42L42_DAC_SRC_PDNB_SHIFT 1
#define CS42L42_DAC_SRC_PDNB_MASK (1 << CS42L42_DAC_SRC_PDNB_SHIFT)
#define CS42L42_ASP_DAI1_PDN_SHIFT 2
#define CS42L42_ASP_DAI1_PDN_MASK (1 << CS42L42_ASP_DAI1_PDN_SHIFT)
#define CS42L42_SRC_PDN_OVERRIDE_SHIFT 3
#define CS42L42_SRC_PDN_OVERRIDE_MASK (1 << CS42L42_SRC_PDN_OVERRIDE_SHIFT)
#define CS42L42_DISCHARGE_FILT_SHIFT 4
#define CS42L42_DISCHARGE_FILT_MASK (1 << CS42L42_DISCHARGE_FILT_SHIFT)
#define CS42L42_PWR_CTL3 (CS42L42_PAGE_11 + 0x03)
#define CS42L42_RING_SENSE_PDNB_SHIFT 1
#define CS42L42_RING_SENSE_PDNB_MASK (1 << CS42L42_RING_SENSE_PDNB_SHIFT)
#define CS42L42_VPMON_PDNB_SHIFT 2
#define CS42L42_VPMON_PDNB_MASK (1 << CS42L42_VPMON_PDNB_SHIFT)
#define CS42L42_SW_CLK_STP_STAT_SEL_SHIFT 5
#define CS42L42_SW_CLK_STP_STAT_SEL_MASK (3 << CS42L42_SW_CLK_STP_STAT_SEL_SHIFT)
#define CS42L42_RSENSE_CTL1 (CS42L42_PAGE_11 + 0x04)
#define CS42L42_RS_TRIM_R_SHIFT 0
#define CS42L42_RS_TRIM_R_MASK (1 << CS42L42_RS_TRIM_R_SHIFT)
#define CS42L42_RS_TRIM_T_SHIFT 1
#define CS42L42_RS_TRIM_T_MASK (1 << CS42L42_RS_TRIM_T_SHIFT)
#define CS42L42_HPREF_RS_SHIFT 2
#define CS42L42_HPREF_RS_MASK (1 << CS42L42_HPREF_RS_SHIFT)
#define CS42L42_HSBIAS_FILT_REF_RS_SHIFT 3
#define CS42L42_HSBIAS_FILT_REF_RS_MASK (1 << CS42L42_HSBIAS_FILT_REF_RS_SHIFT)
#define CS42L42_RING_SENSE_PU_HIZ_SHIFT 6
#define CS42L42_RING_SENSE_PU_HIZ_MASK (1 << CS42L42_RING_SENSE_PU_HIZ_SHIFT)
#define CS42L42_RSENSE_CTL2 (CS42L42_PAGE_11 + 0x05)
#define CS42L42_TS_RS_GATE_SHIFT 7
#define CS42L42_TS_RS_GATE_MAS (1 << CS42L42_TS_RS_GATE_SHIFT)
#define CS42L42_OSC_SWITCH (CS42L42_PAGE_11 + 0x07)
#define CS42L42_SCLK_PRESENT_SHIFT 0
#define CS42L42_SCLK_PRESENT_MASK (1 << CS42L42_SCLK_PRESENT_SHIFT)
#define CS42L42_OSC_SWITCH_STATUS (CS42L42_PAGE_11 + 0x09)
#define CS42L42_OSC_SW_SEL_STAT_SHIFT 0
#define CS42L42_OSC_SW_SEL_STAT_MASK (3 << CS42L42_OSC_SW_SEL_STAT_SHIFT)
#define CS42L42_OSC_PDNB_STAT_SHIFT 2
#define CS42L42_OSC_PDNB_STAT_MASK (1 << CS42L42_OSC_SW_SEL_STAT_SHIFT)
#define CS42L42_RSENSE_CTL3 (CS42L42_PAGE_11 + 0x12)
#define CS42L42_RS_RISE_DBNCE_TIME_SHIFT 0
#define CS42L42_RS_RISE_DBNCE_TIME_MASK (7 << CS42L42_RS_RISE_DBNCE_TIME_SHIFT)
#define CS42L42_RS_FALL_DBNCE_TIME_SHIFT 3
#define CS42L42_RS_FALL_DBNCE_TIME_MASK (7 << CS42L42_RS_FALL_DBNCE_TIME_SHIFT)
#define CS42L42_RS_PU_EN_SHIFT 6
#define CS42L42_RS_PU_EN_MASK (1 << CS42L42_RS_PU_EN_SHIFT)
#define CS42L42_RS_INV_SHIFT 7
#define CS42L42_RS_INV_MASK (1 << CS42L42_RS_INV_SHIFT)
#define CS42L42_TSENSE_CTL (CS42L42_PAGE_11 + 0x13)
#define CS42L42_TS_RISE_DBNCE_TIME_SHIFT 0
#define CS42L42_TS_RISE_DBNCE_TIME_MASK (7 << CS42L42_TS_RISE_DBNCE_TIME_SHIFT)
#define CS42L42_TS_FALL_DBNCE_TIME_SHIFT 3
#define CS42L42_TS_FALL_DBNCE_TIME_MASK (7 << CS42L42_TS_FALL_DBNCE_TIME_SHIFT)
#define CS42L42_TS_INV_SHIFT 7
#define CS42L42_TS_INV_MASK (1 << CS42L42_TS_INV_SHIFT)
#define CS42L42_TSRS_INT_DISABLE (CS42L42_PAGE_11 + 0x14)
#define CS42L42_D_RS_PLUG_DBNC_SHIFT 0
#define CS42L42_D_RS_PLUG_DBNC_MASK (1 << CS42L42_D_RS_PLUG_DBNC_SHIFT)
#define CS42L42_D_RS_UNPLUG_DBNC_SHIFT 1
#define CS42L42_D_RS_UNPLUG_DBNC_MASK (1 << CS42L42_D_RS_UNPLUG_DBNC_SHIFT)
#define CS42L42_D_TS_PLUG_DBNC_SHIFT 2
#define CS42L42_D_TS_PLUG_DBNC_MASK (1 << CS42L42_D_TS_PLUG_DBNC_SHIFT)
#define CS42L42_D_TS_UNPLUG_DBNC_SHIFT 3
#define CS42L42_D_TS_UNPLUG_DBNC_MASK (1 << CS42L42_D_TS_UNPLUG_DBNC_SHIFT)
#define CS42L42_TRSENSE_STATUS (CS42L42_PAGE_11 + 0x15)
#define CS42L42_RS_PLUG_DBNC_SHIFT 0
#define CS42L42_RS_PLUG_DBNC_MASK (1 << CS42L42_RS_PLUG_DBNC_SHIFT)
#define CS42L42_RS_UNPLUG_DBNC_SHIFT 1
#define CS42L42_RS_UNPLUG_DBNC_MASK (1 << CS42L42_RS_UNPLUG_DBNC_SHIFT)
#define CS42L42_TS_PLUG_DBNC_SHIFT 2
#define CS42L42_TS_PLUG_DBNC_MASK (1 << CS42L42_TS_PLUG_DBNC_SHIFT)
#define CS42L42_TS_UNPLUG_DBNC_SHIFT 3
#define CS42L42_TS_UNPLUG_DBNC_MASK (1 << CS42L42_TS_UNPLUG_DBNC_SHIFT)
#define CS42L42_HSDET_CTL1 (CS42L42_PAGE_11 + 0x1F)
#define CS42L42_HSDET_COMP1_LVL_SHIFT 0
#define CS42L42_HSDET_COMP1_LVL_MASK (15 << CS42L42_HSDET_COMP1_LVL_SHIFT)
#define CS42L42_HSDET_COMP2_LVL_SHIFT 4
#define CS42L42_HSDET_COMP2_LVL_MASK (15 << CS42L42_HSDET_COMP2_LVL_SHIFT)
#define CS42L42_HSDET_COMP1_LVL_VAL 12 /* 1.25V Comparator */
#define CS42L42_HSDET_COMP2_LVL_VAL 2 /* 1.75V Comparator */
#define CS42L42_HSDET_COMP1_LVL_DEFAULT 7 /* 1V Comparator */
#define CS42L42_HSDET_COMP2_LVL_DEFAULT 7 /* 2V Comparator */
#define CS42L42_HSDET_CTL2 (CS42L42_PAGE_11 + 0x20)
#define CS42L42_HSDET_AUTO_TIME_SHIFT 0
#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)
#define CS42L42_HSBIAS_REF_SHIFT 3
#define CS42L42_HSBIAS_REF_MASK (1 << CS42L42_HSBIAS_REF_SHIFT)
#define CS42L42_HSDET_SET_SHIFT 4
#define CS42L42_HSDET_SET_MASK (3 << CS42L42_HSDET_SET_SHIFT)
#define CS42L42_HSDET_CTRL_SHIFT 6
#define CS42L42_HSDET_CTRL_MASK (3 << CS42L42_HSDET_CTRL_SHIFT)
#define CS42L42_HS_SWITCH_CTL (CS42L42_PAGE_11 + 0x21)
#define CS42L42_SW_GNDHS_HS4_SHIFT 0
#define CS42L42_SW_GNDHS_HS4_MASK (1 << CS42L42_SW_GNDHS_HS4_SHIFT)
#define CS42L42_SW_GNDHS_HS3_SHIFT 1
#define CS42L42_SW_GNDHS_HS3_MASK (1 << CS42L42_SW_GNDHS_HS3_SHIFT)
#define CS42L42_SW_HSB_HS4_SHIFT 2
#define CS42L42_SW_HSB_HS4_MASK (1 << CS42L42_SW_HSB_HS4_SHIFT)
#define CS42L42_SW_HSB_HS3_SHIFT 3
#define CS42L42_SW_HSB_HS3_MASK (1 << CS42L42_SW_HSB_HS3_SHIFT)
#define CS42L42_SW_HSB_FILT_HS4_SHIFT 4
#define CS42L42_SW_HSB_FILT_HS4_MASK (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT)
#define CS42L42_SW_HSB_FILT_HS3_SHIFT 5
#define CS42L42_SW_HSB_FILT_HS3_MASK (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT)
#define CS42L42_SW_REF_HS4_SHIFT 6
#define CS42L42_SW_REF_HS4_MASK (1 << CS42L42_SW_REF_HS4_SHIFT)
#define CS42L42_SW_REF_HS3_SHIFT 7
#define CS42L42_SW_REF_HS3_MASK (1 << CS42L42_SW_REF_HS3_SHIFT)
#define CS42L42_HS_DET_STATUS (CS42L42_PAGE_11 + 0x24)
#define CS42L42_HSDET_TYPE_SHIFT 0
#define CS42L42_HSDET_TYPE_MASK (3 << CS42L42_HSDET_TYPE_SHIFT)
#define CS42L42_HSDET_COMP1_OUT_SHIFT 6
#define CS42L42_HSDET_COMP1_OUT_MASK (1 << CS42L42_HSDET_COMP1_OUT_SHIFT)
#define CS42L42_HSDET_COMP2_OUT_SHIFT 7
#define CS42L42_HSDET_COMP2_OUT_MASK (1 << CS42L42_HSDET_COMP2_OUT_SHIFT)
#define CS42L42_PLUG_CTIA 0
#define CS42L42_PLUG_OMTP 1
#define CS42L42_PLUG_HEADPHONE 2
#define CS42L42_PLUG_INVALID 3
#define CS42L42_HSDET_SW_COMP1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
(1 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_SW_COMP2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
(0 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_SW_TYPE1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
(1 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_SW_TYPE2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
(0 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_SW_TYPE3 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
(1 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_SW_TYPE4 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
(1 << CS42L42_SW_REF_HS3_SHIFT))
#define CS42L42_HSDET_COMP_TYPE1 1
#define CS42L42_HSDET_COMP_TYPE2 2
#define CS42L42_HSDET_COMP_TYPE3 0
#define CS42L42_HSDET_COMP_TYPE4 3
#define CS42L42_HS_CLAMP_DISABLE (CS42L42_PAGE_11 + 0x29)
#define CS42L42_HS_CLAMP_DISABLE_SHIFT 0
#define CS42L42_HS_CLAMP_DISABLE_MASK (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)
/* Page 0x12 Clocking Registers */
#define CS42L42_MCLK_SRC_SEL (CS42L42_PAGE_12 + 0x01)
#define CS42L42_MCLKDIV_SHIFT 1
#define CS42L42_MCLKDIV_MASK (1 << CS42L42_MCLKDIV_SHIFT)
#define CS42L42_MCLK_SRC_SEL_SHIFT 0
#define CS42L42_MCLK_SRC_SEL_MASK (1 << CS42L42_MCLK_SRC_SEL_SHIFT)
#define CS42L42_SPDIF_CLK_CFG (CS42L42_PAGE_12 + 0x02)
#define CS42L42_FSYNC_PW_LOWER (CS42L42_PAGE_12 + 0x03)
#define CS42L42_FSYNC_PW_UPPER (CS42L42_PAGE_12 + 0x04)
#define CS42L42_FSYNC_PULSE_WIDTH_SHIFT 0
#define CS42L42_FSYNC_PULSE_WIDTH_MASK (0xff << \
CS42L42_FSYNC_PULSE_WIDTH_SHIFT)
#define CS42L42_FSYNC_P_LOWER (CS42L42_PAGE_12 + 0x05)
#define CS42L42_FSYNC_P_UPPER (CS42L42_PAGE_12 + 0x06)
#define CS42L42_FSYNC_PERIOD_SHIFT 0
#define CS42L42_FSYNC_PERIOD_MASK (0xff << CS42L42_FSYNC_PERIOD_SHIFT)
#define CS42L42_ASP_CLK_CFG (CS42L42_PAGE_12 + 0x07)
#define CS42L42_ASP_SCLK_EN_SHIFT 5
#define CS42L42_ASP_SCLK_EN_MASK (1 << CS42L42_ASP_SCLK_EN_SHIFT)
#define CS42L42_ASP_MASTER_MODE 0x01
#define CS42L42_ASP_SLAVE_MODE 0x00
#define CS42L42_ASP_MODE_SHIFT 4
#define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT)
#define CS42L42_ASP_SCPOL_SHIFT 2
#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT)
#define CS42L42_ASP_SCPOL_NOR 3
#define CS42L42_ASP_LCPOL_SHIFT 0
#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT)
#define CS42L42_ASP_LCPOL_INV 3
#define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08)
#define CS42L42_ASP_STP_SHIFT 4
#define CS42L42_ASP_STP_MASK (1 << CS42L42_ASP_STP_SHIFT)
#define CS42L42_ASP_5050_SHIFT 3
#define CS42L42_ASP_5050_MASK (1 << CS42L42_ASP_5050_SHIFT)
#define CS42L42_ASP_FSD_SHIFT 0
#define CS42L42_ASP_FSD_MASK (7 << CS42L42_ASP_FSD_SHIFT)
#define CS42L42_ASP_FSD_0_5 1
#define CS42L42_ASP_FSD_1_0 2
#define CS42L42_ASP_FSD_1_5 3
#define CS42L42_ASP_FSD_2_0 4
#define CS42L42_FS_RATE_EN (CS42L42_PAGE_12 + 0x09)
#define CS42L42_FS_EN_SHIFT 0
#define CS42L42_FS_EN_MASK (0xf << CS42L42_FS_EN_SHIFT)
#define CS42L42_FS_EN_IASRC_96K 0x1
#define CS42L42_FS_EN_OASRC_96K 0x2
#define CS42L42_IN_ASRC_CLK (CS42L42_PAGE_12 + 0x0A)
#define CS42L42_CLK_IASRC_SEL_SHIFT 0
#define CS42L42_CLK_IASRC_SEL_MASK (1 << CS42L42_CLK_IASRC_SEL_SHIFT)
#define CS42L42_CLK_IASRC_SEL_6 0
#define CS42L42_CLK_IASRC_SEL_12 1
#define CS42L42_OUT_ASRC_CLK (CS42L42_PAGE_12 + 0x0B)
#define CS42L42_CLK_OASRC_SEL_SHIFT 0
#define CS42L42_CLK_OASRC_SEL_MASK (1 << CS42L42_CLK_OASRC_SEL_SHIFT)
#define CS42L42_CLK_OASRC_SEL_12 1
#define CS42L42_PLL_DIV_CFG1 (CS42L42_PAGE_12 + 0x0C)
#define CS42L42_SCLK_PREDIV_SHIFT 0
#define CS42L42_SCLK_PREDIV_MASK (3 << CS42L42_SCLK_PREDIV_SHIFT)
/* Page 0x13 Interrupt Registers */
/* Interrupts */
#define CS42L42_ADC_OVFL_STATUS (CS42L42_PAGE_13 + 0x01)
#define CS42L42_MIXER_STATUS (CS42L42_PAGE_13 + 0x02)
#define CS42L42_SRC_STATUS (CS42L42_PAGE_13 + 0x03)
#define CS42L42_ASP_RX_STATUS (CS42L42_PAGE_13 + 0x04)
#define CS42L42_ASP_TX_STATUS (CS42L42_PAGE_13 + 0x05)
#define CS42L42_CODEC_STATUS (CS42L42_PAGE_13 + 0x08)
#define CS42L42_DET_INT_STATUS1 (CS42L42_PAGE_13 + 0x09)
#define CS42L42_DET_INT_STATUS2 (CS42L42_PAGE_13 + 0x0A)
#define CS42L42_SRCPL_INT_STATUS (CS42L42_PAGE_13 + 0x0B)
#define CS42L42_VPMON_STATUS (CS42L42_PAGE_13 + 0x0D)
#define CS42L42_PLL_LOCK_STATUS (CS42L42_PAGE_13 + 0x0E)
#define CS42L42_TSRS_PLUG_STATUS (CS42L42_PAGE_13 + 0x0F)
/* Masks */
#define CS42L42_ADC_OVFL_INT_MASK (CS42L42_PAGE_13 + 0x16)
#define CS42L42_ADC_OVFL_SHIFT 0
#define CS42L42_ADC_OVFL_MASK (1 << CS42L42_ADC_OVFL_SHIFT)
#define CS42L42_ADC_OVFL_VAL_MASK CS42L42_ADC_OVFL_MASK
#define CS42L42_MIXER_INT_MASK (CS42L42_PAGE_13 + 0x17)
#define CS42L42_MIX_CHB_OVFL_SHIFT 0
#define CS42L42_MIX_CHB_OVFL_MASK (1 << CS42L42_MIX_CHB_OVFL_SHIFT)
#define CS42L42_MIX_CHA_OVFL_SHIFT 1
#define CS42L42_MIX_CHA_OVFL_MASK (1 << CS42L42_MIX_CHA_OVFL_SHIFT)
#define CS42L42_EQ_OVFL_SHIFT 2
#define CS42L42_EQ_OVFL_MASK (1 << CS42L42_EQ_OVFL_SHIFT)
#define CS42L42_EQ_BIQUAD_OVFL_SHIFT 3
#define CS42L42_EQ_BIQUAD_OVFL_MASK (1 << CS42L42_EQ_BIQUAD_OVFL_SHIFT)
#define CS42L42_MIXER_VAL_MASK (CS42L42_MIX_CHB_OVFL_MASK | \
CS42L42_MIX_CHA_OVFL_MASK | \
CS42L42_EQ_OVFL_MASK | \
CS42L42_EQ_BIQUAD_OVFL_MASK)
#define CS42L42_SRC_INT_MASK (CS42L42_PAGE_13 + 0x18)
#define CS42L42_SRC_ILK_SHIFT 0
#define CS42L42_SRC_ILK_MASK (1 << CS42L42_SRC_ILK_SHIFT)
#define CS42L42_SRC_OLK_SHIFT 1
#define CS42L42_SRC_OLK_MASK (1 << CS42L42_SRC_OLK_SHIFT)
#define CS42L42_SRC_IUNLK_SHIFT 2
#define CS42L42_SRC_IUNLK_MASK (1 << CS42L42_SRC_IUNLK_SHIFT)
#define CS42L42_SRC_OUNLK_SHIFT 3
#define CS42L42_SRC_OUNLK_MASK (1 << CS42L42_SRC_OUNLK_SHIFT)
#define CS42L42_SRC_VAL_MASK (CS42L42_SRC_ILK_MASK | \
CS42L42_SRC_OLK_MASK | \
CS42L42_SRC_IUNLK_MASK | \
CS42L42_SRC_OUNLK_MASK)
#define CS42L42_ASP_RX_INT_MASK (CS42L42_PAGE_13 + 0x19)
#define CS42L42_ASPRX_NOLRCK_SHIFT 0
#define CS42L42_ASPRX_NOLRCK_MASK (1 << CS42L42_ASPRX_NOLRCK_SHIFT)
#define CS42L42_ASPRX_EARLY_SHIFT 1
#define CS42L42_ASPRX_EARLY_MASK (1 << CS42L42_ASPRX_EARLY_SHIFT)
#define CS42L42_ASPRX_LATE_SHIFT 2
#define CS42L42_ASPRX_LATE_MASK (1 << CS42L42_ASPRX_LATE_SHIFT)
#define CS42L42_ASPRX_ERROR_SHIFT 3
#define CS42L42_ASPRX_ERROR_MASK (1 << CS42L42_ASPRX_ERROR_SHIFT)
#define CS42L42_ASPRX_OVLD_SHIFT 4
#define CS42L42_ASPRX_OVLD_MASK (1 << CS42L42_ASPRX_OVLD_SHIFT)
#define CS42L42_ASP_RX_VAL_MASK (CS42L42_ASPRX_NOLRCK_MASK | \
CS42L42_ASPRX_EARLY_MASK | \
CS42L42_ASPRX_LATE_MASK | \
CS42L42_ASPRX_ERROR_MASK | \
CS42L42_ASPRX_OVLD_MASK)
#define CS42L42_ASP_TX_INT_MASK (CS42L42_PAGE_13 + 0x1A)
#define CS42L42_ASPTX_NOLRCK_SHIFT 0
#define CS42L42_ASPTX_NOLRCK_MASK (1 << CS42L42_ASPTX_NOLRCK_SHIFT)
#define CS42L42_ASPTX_EARLY_SHIFT 1
#define CS42L42_ASPTX_EARLY_MASK (1 << CS42L42_ASPTX_EARLY_SHIFT)
#define CS42L42_ASPTX_LATE_SHIFT 2
#define CS42L42_ASPTX_LATE_MASK (1 << CS42L42_ASPTX_LATE_SHIFT)
#define CS42L42_ASPTX_SMERROR_SHIFT 3
#define CS42L42_ASPTX_SMERROR_MASK (1 << CS42L42_ASPTX_SMERROR_SHIFT)
#define CS42L42_ASP_TX_VAL_MASK (CS42L42_ASPTX_NOLRCK_MASK | \
CS42L42_ASPTX_EARLY_MASK | \
CS42L42_ASPTX_LATE_MASK | \
CS42L42_ASPTX_SMERROR_MASK)
#define CS42L42_CODEC_INT_MASK (CS42L42_PAGE_13 + 0x1B)
#define CS42L42_PDN_DONE_SHIFT 0
#define CS42L42_PDN_DONE_MASK (1 << CS42L42_PDN_DONE_SHIFT)
#define CS42L42_HSDET_AUTO_DONE_SHIFT 1
#define CS42L42_HSDET_AUTO_DONE_MASK (1 << CS42L42_HSDET_AUTO_DONE_SHIFT)
#define CS42L42_CODEC_VAL_MASK (CS42L42_PDN_DONE_MASK | \
CS42L42_HSDET_AUTO_DONE_MASK)
#define CS42L42_SRCPL_INT_MASK (CS42L42_PAGE_13 + 0x1C)
#define CS42L42_SRCPL_ADC_LK_SHIFT 0
#define CS42L42_SRCPL_ADC_LK_MASK (1 << CS42L42_SRCPL_ADC_LK_SHIFT)
#define CS42L42_SRCPL_DAC_LK_SHIFT 2
#define CS42L42_SRCPL_DAC_LK_MASK (1 << CS42L42_SRCPL_DAC_LK_SHIFT)
#define CS42L42_SRCPL_ADC_UNLK_SHIFT 5
#define CS42L42_SRCPL_ADC_UNLK_MASK (1 << CS42L42_SRCPL_ADC_UNLK_SHIFT)
#define CS42L42_SRCPL_DAC_UNLK_SHIFT 6
#define CS42L42_SRCPL_DAC_UNLK_MASK (1 << CS42L42_SRCPL_DAC_UNLK_SHIFT)
#define CS42L42_SRCPL_VAL_MASK (CS42L42_SRCPL_ADC_LK_MASK | \
CS42L42_SRCPL_DAC_LK_MASK | \
CS42L42_SRCPL_ADC_UNLK_MASK | \
CS42L42_SRCPL_DAC_UNLK_MASK)
#define CS42L42_VPMON_INT_MASK (CS42L42_PAGE_13 + 0x1E)
#define CS42L42_VPMON_SHIFT 0
#define CS42L42_VPMON_MASK (1 << CS42L42_VPMON_SHIFT)
#define CS42L42_VPMON_VAL_MASK CS42L42_VPMON_MASK
#define CS42L42_PLL_LOCK_INT_MASK (CS42L42_PAGE_13 + 0x1F)
#define CS42L42_PLL_LOCK_SHIFT 0
#define CS42L42_PLL_LOCK_MASK (1 << CS42L42_PLL_LOCK_SHIFT)
#define CS42L42_PLL_LOCK_VAL_MASK CS42L42_PLL_LOCK_MASK
#define CS42L42_TSRS_PLUG_INT_MASK (CS42L42_PAGE_13 + 0x20)
#define CS42L42_RS_PLUG_SHIFT 0
#define CS42L42_RS_PLUG_MASK (1 << CS42L42_RS_PLUG_SHIFT)
#define CS42L42_RS_UNPLUG_SHIFT 1
#define CS42L42_RS_UNPLUG_MASK (1 << CS42L42_RS_UNPLUG_SHIFT)
#define CS42L42_TS_PLUG_SHIFT 2
#define CS42L42_TS_PLUG_MASK (1 << CS42L42_TS_PLUG_SHIFT)
#define CS42L42_TS_UNPLUG_SHIFT 3
#define CS42L42_TS_UNPLUG_MASK (1 << CS42L42_TS_UNPLUG_SHIFT)
#define CS42L42_TSRS_PLUG_VAL_MASK (CS42L42_RS_PLUG_MASK | \
CS42L42_RS_UNPLUG_MASK | \
CS42L42_TS_PLUG_MASK | \
CS42L42_TS_UNPLUG_MASK)
#define CS42L42_TS_PLUG 3
#define CS42L42_TS_UNPLUG 0
#define CS42L42_TS_TRANS 1
/*
* NOTE: PLL_START must be 0 while both ADC_PDN=1 and HP_PDN=1.
* Otherwise it will prevent FILT+ from charging properly.
*/
#define CS42L42_PLL_CTL1 (CS42L42_PAGE_15 + 0x01)
#define CS42L42_PLL_START_SHIFT 0
#define CS42L42_PLL_START_MASK (1 << CS42L42_PLL_START_SHIFT)
#define CS42L42_PLL_DIV_FRAC0 (CS42L42_PAGE_15 + 0x02)
#define CS42L42_PLL_DIV_FRAC_SHIFT 0
#define CS42L42_PLL_DIV_FRAC_MASK (0xff << CS42L42_PLL_DIV_FRAC_SHIFT)
#define CS42L42_PLL_DIV_FRAC1 (CS42L42_PAGE_15 + 0x03)
#define CS42L42_PLL_DIV_FRAC2 (CS42L42_PAGE_15 + 0x04)
#define CS42L42_PLL_DIV_INT (CS42L42_PAGE_15 + 0x05)
#define CS42L42_PLL_DIV_INT_SHIFT 0
#define CS42L42_PLL_DIV_INT_MASK (0xff << CS42L42_PLL_DIV_INT_SHIFT)
#define CS42L42_PLL_CTL3 (CS42L42_PAGE_15 + 0x08)
#define CS42L42_PLL_DIVOUT_SHIFT 0
#define CS42L42_PLL_DIVOUT_MASK (0xff << CS42L42_PLL_DIVOUT_SHIFT)
#define CS42L42_PLL_CAL_RATIO (CS42L42_PAGE_15 + 0x0A)
#define CS42L42_PLL_CAL_RATIO_SHIFT 0
#define CS42L42_PLL_CAL_RATIO_MASK (0xff << CS42L42_PLL_CAL_RATIO_SHIFT)
#define CS42L42_PLL_CTL4 (CS42L42_PAGE_15 + 0x1B)
#define CS42L42_PLL_MODE_SHIFT 0
#define CS42L42_PLL_MODE_MASK (3 << CS42L42_PLL_MODE_SHIFT)
/* Page 0x19 HP Load Detect Registers */
#define CS42L42_LOAD_DET_RCSTAT (CS42L42_PAGE_19 + 0x25)
#define CS42L42_RLA_STAT_SHIFT 0
#define CS42L42_RLA_STAT_MASK (3 << CS42L42_RLA_STAT_SHIFT)
#define CS42L42_RLA_STAT_15_OHM 0
#define CS42L42_LOAD_DET_DONE (CS42L42_PAGE_19 + 0x26)
#define CS42L42_HPLOAD_DET_DONE_SHIFT 0
#define CS42L42_HPLOAD_DET_DONE_MASK (1 << CS42L42_HPLOAD_DET_DONE_SHIFT)
#define CS42L42_LOAD_DET_EN (CS42L42_PAGE_19 + 0x27)
#define CS42L42_HP_LD_EN_SHIFT 0
#define CS42L42_HP_LD_EN_MASK (1 << CS42L42_HP_LD_EN_SHIFT)
/* Page 0x1B Headset Interface Registers */
#define CS42L42_HSBIAS_SC_AUTOCTL (CS42L42_PAGE_1B + 0x70)
#define CS42L42_HSBIAS_SENSE_TRIP_SHIFT 0
#define CS42L42_HSBIAS_SENSE_TRIP_MASK (7 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT)
#define CS42L42_TIP_SENSE_EN_SHIFT 5
#define CS42L42_TIP_SENSE_EN_MASK (1 << CS42L42_TIP_SENSE_EN_SHIFT)
#define CS42L42_AUTO_HSBIAS_HIZ_SHIFT 6
#define CS42L42_AUTO_HSBIAS_HIZ_MASK (1 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT)
#define CS42L42_HSBIAS_SENSE_EN_SHIFT 7
#define CS42L42_HSBIAS_SENSE_EN_MASK (1 << CS42L42_HSBIAS_SENSE_EN_SHIFT)
#define CS42L42_WAKE_CTL (CS42L42_PAGE_1B + 0x71)
#define CS42L42_WAKEB_CLEAR_SHIFT 0
#define CS42L42_WAKEB_CLEAR_MASK (1 << CS42L42_WAKEB_CLEAR_SHIFT)
#define CS42L42_WAKEB_MODE_SHIFT 5
#define CS42L42_WAKEB_MODE_MASK (1 << CS42L42_WAKEB_MODE_SHIFT)
#define CS42L42_M_HP_WAKE_SHIFT 6
#define CS42L42_M_HP_WAKE_MASK (1 << CS42L42_M_HP_WAKE_SHIFT)
#define CS42L42_M_MIC_WAKE_SHIFT 7
#define CS42L42_M_MIC_WAKE_MASK (1 << CS42L42_M_MIC_WAKE_SHIFT)
#define CS42L42_ADC_DISABLE_MUTE (CS42L42_PAGE_1B + 0x72)
#define CS42L42_ADC_DISABLE_S0_MUTE_SHIFT 7
#define CS42L42_ADC_DISABLE_S0_MUTE_MASK (1 << CS42L42_ADC_DISABLE_S0_MUTE_SHIFT)
#define CS42L42_TIPSENSE_CTL (CS42L42_PAGE_1B + 0x73)
#define CS42L42_TIP_SENSE_DEBOUNCE_SHIFT 0
#define CS42L42_TIP_SENSE_DEBOUNCE_MASK (3 << CS42L42_TIP_SENSE_DEBOUNCE_SHIFT)
#define CS42L42_TIP_SENSE_INV_SHIFT 5
#define CS42L42_TIP_SENSE_INV_MASK (1 << CS42L42_TIP_SENSE_INV_SHIFT)
#define CS42L42_TIP_SENSE_CTRL_SHIFT 6
#define CS42L42_TIP_SENSE_CTRL_MASK (3 << CS42L42_TIP_SENSE_CTRL_SHIFT)
/*
* NOTE: DETECT_MODE must be 0 while both ADC_PDN=1 and HP_PDN=1.
* Otherwise it will prevent FILT+ from charging properly.
*/
#define CS42L42_MISC_DET_CTL (CS42L42_PAGE_1B + 0x74)
#define CS42L42_PDN_MIC_LVL_DET_SHIFT 0
#define CS42L42_PDN_MIC_LVL_DET_MASK (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT)
#define CS42L42_HSBIAS_CTL_SHIFT 1
#define CS42L42_HSBIAS_CTL_MASK (3 << CS42L42_HSBIAS_CTL_SHIFT)
#define CS42L42_DETECT_MODE_SHIFT 3
#define CS42L42_DETECT_MODE_MASK (3 << CS42L42_DETECT_MODE_SHIFT)
#define CS42L42_MIC_DET_CTL1 (CS42L42_PAGE_1B + 0x75)
#define CS42L42_HS_DET_LEVEL_SHIFT 0
#define CS42L42_HS_DET_LEVEL_MASK (0x3F << CS42L42_HS_DET_LEVEL_SHIFT)
#define CS42L42_EVENT_STAT_SEL_SHIFT 6
#define CS42L42_EVENT_STAT_SEL_MASK (1 << CS42L42_EVENT_STAT_SEL_SHIFT)
#define CS42L42_LATCH_TO_VP_SHIFT 7
#define CS42L42_LATCH_TO_VP_MASK (1 << CS42L42_LATCH_TO_VP_SHIFT)
#define CS42L42_MIC_DET_CTL2 (CS42L42_PAGE_1B + 0x76)
#define CS42L42_DEBOUNCE_TIME_SHIFT 5
#define CS42L42_DEBOUNCE_TIME_MASK (0x07 << CS42L42_DEBOUNCE_TIME_SHIFT)
#define CS42L42_DET_STATUS1 (CS42L42_PAGE_1B + 0x77)
#define CS42L42_HSBIAS_HIZ_MODE_SHIFT 6
#define CS42L42_HSBIAS_HIZ_MODE_MASK (1 << CS42L42_HSBIAS_HIZ_MODE_SHIFT)
#define CS42L42_TIP_SENSE_SHIFT 7
#define CS42L42_TIP_SENSE_MASK (1 << CS42L42_TIP_SENSE_SHIFT)
#define CS42L42_DET_STATUS2 (CS42L42_PAGE_1B + 0x78)
#define CS42L42_SHORT_TRUE_SHIFT 0
#define CS42L42_SHORT_TRUE_MASK (1 << CS42L42_SHORT_TRUE_SHIFT)
#define CS42L42_HS_TRUE_SHIFT 1
#define CS42L42_HS_TRUE_MASK (1 << CS42L42_HS_TRUE_SHIFT)
#define CS42L42_DET_INT1_MASK (CS42L42_PAGE_1B + 0x79)
#define CS42L42_TIP_SENSE_UNPLUG_SHIFT 5
#define CS42L42_TIP_SENSE_UNPLUG_MASK (1 << CS42L42_TIP_SENSE_UNPLUG_SHIFT)
#define CS42L42_TIP_SENSE_PLUG_SHIFT 6
#define CS42L42_TIP_SENSE_PLUG_MASK (1 << CS42L42_TIP_SENSE_PLUG_SHIFT)
#define CS42L42_HSBIAS_SENSE_SHIFT 7
#define CS42L42_HSBIAS_SENSE_MASK (1 << CS42L42_HSBIAS_SENSE_SHIFT)
#define CS42L42_DET_INT_VAL1_MASK (CS42L42_TIP_SENSE_UNPLUG_MASK | \
CS42L42_TIP_SENSE_PLUG_MASK | \
CS42L42_HSBIAS_SENSE_MASK)
#define CS42L42_DET_INT2_MASK (CS42L42_PAGE_1B + 0x7A)
#define CS42L42_M_SHORT_DET_SHIFT 0
#define CS42L42_M_SHORT_DET_MASK (1 << CS42L42_M_SHORT_DET_SHIFT)
#define CS42L42_M_SHORT_RLS_SHIFT 1
#define CS42L42_M_SHORT_RLS_MASK (1 << CS42L42_M_SHORT_RLS_SHIFT)
#define CS42L42_M_HSBIAS_HIZ_SHIFT 2
#define CS42L42_M_HSBIAS_HIZ_MASK (1 << CS42L42_M_HSBIAS_HIZ_SHIFT)
#define CS42L42_M_DETECT_FT_SHIFT 6
#define CS42L42_M_DETECT_FT_MASK (1 << CS42L42_M_DETECT_FT_SHIFT)
#define CS42L42_M_DETECT_TF_SHIFT 7
#define CS42L42_M_DETECT_TF_MASK (1 << CS42L42_M_DETECT_TF_SHIFT)
#define CS42L42_DET_INT_VAL2_MASK (CS42L42_M_SHORT_DET_MASK | \
CS42L42_M_SHORT_RLS_MASK | \
CS42L42_M_HSBIAS_HIZ_MASK | \
CS42L42_M_DETECT_FT_MASK | \
CS42L42_M_DETECT_TF_MASK)
/* Page 0x1C Headset Bias Registers */
#define CS42L42_HS_BIAS_CTL (CS42L42_PAGE_1C + 0x03)
#define CS42L42_HSBIAS_RAMP_SHIFT 0
#define CS42L42_HSBIAS_RAMP_MASK (3 << CS42L42_HSBIAS_RAMP_SHIFT)
#define CS42L42_HSBIAS_PD_SHIFT 4
#define CS42L42_HSBIAS_PD_MASK (1 << CS42L42_HSBIAS_PD_SHIFT)
#define CS42L42_HSBIAS_CAPLESS_SHIFT 7
#define CS42L42_HSBIAS_CAPLESS_MASK (1 << CS42L42_HSBIAS_CAPLESS_SHIFT)
/* Page 0x1D ADC Registers */
#define CS42L42_ADC_CTL (CS42L42_PAGE_1D + 0x01)
#define CS42L42_ADC_NOTCH_DIS_SHIFT 5
#define CS42L42_ADC_FORCE_WEAK_VCM_SHIFT 4
#define CS42L42_ADC_INV_SHIFT 2
#define CS42L42_ADC_DIG_BOOST_SHIFT 0
#define CS42L42_ADC_VOLUME (CS42L42_PAGE_1D + 0x03)
#define CS42L42_ADC_VOL_SHIFT 0
#define CS42L42_ADC_WNF_HPF_CTL (CS42L42_PAGE_1D + 0x04)
#define CS42L42_ADC_WNF_CF_SHIFT 4
#define CS42L42_ADC_WNF_EN_SHIFT 3
#define CS42L42_ADC_HPF_CF_SHIFT 1
#define CS42L42_ADC_HPF_EN_SHIFT 0
/* Page 0x1F DAC Registers */
#define CS42L42_DAC_CTL1 (CS42L42_PAGE_1F + 0x01)
#define CS42L42_DACB_INV_SHIFT 1
#define CS42L42_DACA_INV_SHIFT 0
#define CS42L42_DAC_CTL2 (CS42L42_PAGE_1F + 0x06)
#define CS42L42_HPOUT_PULLDOWN_SHIFT 4
#define CS42L42_HPOUT_PULLDOWN_MASK (15 << CS42L42_HPOUT_PULLDOWN_SHIFT)
#define CS42L42_HPOUT_LOAD_SHIFT 3
#define CS42L42_HPOUT_LOAD_MASK (1 << CS42L42_HPOUT_LOAD_SHIFT)
#define CS42L42_HPOUT_CLAMP_SHIFT 2
#define CS42L42_HPOUT_CLAMP_MASK (1 << CS42L42_HPOUT_CLAMP_SHIFT)
#define CS42L42_DAC_HPF_EN_SHIFT 1
#define CS42L42_DAC_HPF_EN_MASK (1 << CS42L42_DAC_HPF_EN_SHIFT)
#define CS42L42_DAC_MON_EN_SHIFT 0
#define CS42L42_DAC_MON_EN_MASK (1 << CS42L42_DAC_MON_EN_SHIFT)
/* Page 0x20 HP CTL Registers */
#define CS42L42_HP_CTL (CS42L42_PAGE_20 + 0x01)
#define CS42L42_HP_ANA_BMUTE_SHIFT 3
#define CS42L42_HP_ANA_BMUTE_MASK (1 << CS42L42_HP_ANA_BMUTE_SHIFT)
#define CS42L42_HP_ANA_AMUTE_SHIFT 2
#define CS42L42_HP_ANA_AMUTE_MASK (1 << CS42L42_HP_ANA_AMUTE_SHIFT)
#define CS42L42_HP_FULL_SCALE_VOL_SHIFT 1
#define CS42L42_HP_FULL_SCALE_VOL_MASK (1 << CS42L42_HP_FULL_SCALE_VOL_SHIFT)
/* Page 0x21 Class H Registers */
#define CS42L42_CLASSH_CTL (CS42L42_PAGE_21 + 0x01)
/* Page 0x23 Mixer Volume Registers */
#define CS42L42_MIXER_CHA_VOL (CS42L42_PAGE_23 + 0x01)
#define CS42L42_MIXER_ADC_VOL (CS42L42_PAGE_23 + 0x02)
#define CS42L42_MIXER_CHB_VOL (CS42L42_PAGE_23 + 0x03)
#define CS42L42_MIXER_CH_VOL_SHIFT 0
#define CS42L42_MIXER_CH_VOL_MASK (0x3f << CS42L42_MIXER_CH_VOL_SHIFT)
/* Page 0x24 EQ Registers */
#define CS42L42_EQ_COEF_IN0 (CS42L42_PAGE_24 + 0x01)
#define CS42L42_EQ_COEF_IN1 (CS42L42_PAGE_24 + 0x02)
#define CS42L42_EQ_COEF_IN2 (CS42L42_PAGE_24 + 0x03)
#define CS42L42_EQ_COEF_IN3 (CS42L42_PAGE_24 + 0x04)
#define CS42L42_EQ_COEF_RW (CS42L42_PAGE_24 + 0x06)
#define CS42L42_EQ_COEF_OUT0 (CS42L42_PAGE_24 + 0x07)
#define CS42L42_EQ_COEF_OUT1 (CS42L42_PAGE_24 + 0x08)
#define CS42L42_EQ_COEF_OUT2 (CS42L42_PAGE_24 + 0x09)
#define CS42L42_EQ_COEF_OUT3 (CS42L42_PAGE_24 + 0x0A)
#define CS42L42_EQ_INIT_STAT (CS42L42_PAGE_24 + 0x0B)
#define CS42L42_EQ_START_FILT (CS42L42_PAGE_24 + 0x0C)
#define CS42L42_EQ_MUTE_CTL (CS42L42_PAGE_24 + 0x0E)
/* Page 0x25 Audio Port Registers */
#define CS42L42_SP_RX_CH_SEL (CS42L42_PAGE_25 + 0x01)
#define CS42L42_SP_RX_CHB_SEL_SHIFT 2
#define CS42L42_SP_RX_CHB_SEL_MASK (3 << CS42L42_SP_RX_CHB_SEL_SHIFT)
#define CS42L42_SP_RX_ISOC_CTL (CS42L42_PAGE_25 + 0x02)
#define CS42L42_SP_RX_RSYNC_SHIFT 6
#define CS42L42_SP_RX_RSYNC_MASK (1 << CS42L42_SP_RX_RSYNC_SHIFT)
#define CS42L42_SP_RX_NSB_POS_SHIFT 3
#define CS42L42_SP_RX_NSB_POS_MASK (7 << CS42L42_SP_RX_NSB_POS_SHIFT)
#define CS42L42_SP_RX_NFS_NSBB_SHIFT 2
#define CS42L42_SP_RX_NFS_NSBB_MASK (1 << CS42L42_SP_RX_NFS_NSBB_SHIFT)
#define CS42L42_SP_RX_ISOC_MODE_SHIFT 0
#define CS42L42_SP_RX_ISOC_MODE_MASK (3 << CS42L42_SP_RX_ISOC_MODE_SHIFT)
#define CS42L42_SP_RX_FS (CS42L42_PAGE_25 + 0x03)
#define CS42l42_SPDIF_CH_SEL (CS42L42_PAGE_25 + 0x04)
#define CS42L42_SP_TX_ISOC_CTL (CS42L42_PAGE_25 + 0x05)
#define CS42L42_SP_TX_FS (CS42L42_PAGE_25 + 0x06)
#define CS42L42_SPDIF_SW_CTL1 (CS42L42_PAGE_25 + 0x07)
/* Page 0x26 SRC Registers */
#define CS42L42_SRC_SDIN_FS (CS42L42_PAGE_26 + 0x01)
#define CS42L42_SRC_SDIN_FS_SHIFT 0
#define CS42L42_SRC_SDIN_FS_MASK (0x1f << CS42L42_SRC_SDIN_FS_SHIFT)
#define CS42L42_SRC_SDOUT_FS (CS42L42_PAGE_26 + 0x09)
/* Page 0x28 S/PDIF Registers */
#define CS42L42_SPDIF_CTL1 (CS42L42_PAGE_28 + 0x01)
#define CS42L42_SPDIF_CTL2 (CS42L42_PAGE_28 + 0x02)
#define CS42L42_SPDIF_CTL3 (CS42L42_PAGE_28 + 0x03)
#define CS42L42_SPDIF_CTL4 (CS42L42_PAGE_28 + 0x04)
/* Page 0x29 Serial Port TX Registers */
#define CS42L42_ASP_TX_SZ_EN (CS42L42_PAGE_29 + 0x01)
#define CS42L42_ASP_TX_EN_SHIFT 0
#define CS42L42_ASP_TX_CH_EN (CS42L42_PAGE_29 + 0x02)
#define CS42L42_ASP_TX0_CH2_SHIFT 1
#define CS42L42_ASP_TX0_CH1_SHIFT 0
#define CS42L42_ASP_TX_CH_AP_RES (CS42L42_PAGE_29 + 0x03)
#define CS42L42_ASP_TX_CH1_AP_SHIFT 7
#define CS42L42_ASP_TX_CH1_AP_MASK (1 << CS42L42_ASP_TX_CH1_AP_SHIFT)
#define CS42L42_ASP_TX_CH2_AP_SHIFT 6
#define CS42L42_ASP_TX_CH2_AP_MASK (1 << CS42L42_ASP_TX_CH2_AP_SHIFT)
#define CS42L42_ASP_TX_CH2_RES_SHIFT 2
#define CS42L42_ASP_TX_CH2_RES_MASK (3 << CS42L42_ASP_TX_CH2_RES_SHIFT)
#define CS42L42_ASP_TX_CH1_RES_SHIFT 0
#define CS42L42_ASP_TX_CH1_RES_MASK (3 << CS42L42_ASP_TX_CH1_RES_SHIFT)
#define CS42L42_ASP_TX_CH1_BIT_MSB (CS42L42_PAGE_29 + 0x04)
#define CS42L42_ASP_TX_CH1_BIT_LSB (CS42L42_PAGE_29 + 0x05)
#define CS42L42_ASP_TX_HIZ_DLY_CFG (CS42L42_PAGE_29 + 0x06)
#define CS42L42_ASP_TX_CH2_BIT_MSB (CS42L42_PAGE_29 + 0x0A)
#define CS42L42_ASP_TX_CH2_BIT_LSB (CS42L42_PAGE_29 + 0x0B)
/* Page 0x2A Serial Port RX Registers */
#define CS42L42_ASP_RX_DAI0_EN (CS42L42_PAGE_2A + 0x01)
#define CS42L42_ASP_RX0_CH_EN_SHIFT 2
#define CS42L42_ASP_RX0_CH_EN_MASK (0xf << CS42L42_ASP_RX0_CH_EN_SHIFT)
#define CS42L42_ASP_RX0_CH1_SHIFT 2
#define CS42L42_ASP_RX0_CH2_SHIFT 3
#define CS42L42_ASP_RX0_CH3_SHIFT 4
#define CS42L42_ASP_RX0_CH4_SHIFT 5
#define CS42L42_ASP_RX_DAI0_CH1_AP_RES (CS42L42_PAGE_2A + 0x02)
#define CS42L42_ASP_RX_DAI0_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x03)
#define CS42L42_ASP_RX_DAI0_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x04)
#define CS42L42_ASP_RX_DAI0_CH2_AP_RES (CS42L42_PAGE_2A + 0x05)
#define CS42L42_ASP_RX_DAI0_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x06)
#define CS42L42_ASP_RX_DAI0_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x07)
#define CS42L42_ASP_RX_DAI0_CH3_AP_RES (CS42L42_PAGE_2A + 0x08)
#define CS42L42_ASP_RX_DAI0_CH3_BIT_MSB (CS42L42_PAGE_2A + 0x09)
#define CS42L42_ASP_RX_DAI0_CH3_BIT_LSB (CS42L42_PAGE_2A + 0x0A)
#define CS42L42_ASP_RX_DAI0_CH4_AP_RES (CS42L42_PAGE_2A + 0x0B)
#define CS42L42_ASP_RX_DAI0_CH4_BIT_MSB (CS42L42_PAGE_2A + 0x0C)
#define CS42L42_ASP_RX_DAI0_CH4_BIT_LSB (CS42L42_PAGE_2A + 0x0D)
#define CS42L42_ASP_RX_DAI1_CH1_AP_RES (CS42L42_PAGE_2A + 0x0E)
#define CS42L42_ASP_RX_DAI1_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x0F)
#define CS42L42_ASP_RX_DAI1_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x10)
#define CS42L42_ASP_RX_DAI1_CH2_AP_RES (CS42L42_PAGE_2A + 0x11)
#define CS42L42_ASP_RX_DAI1_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x12)
#define CS42L42_ASP_RX_DAI1_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x13)
#define CS42L42_ASP_RX_CH_AP_SHIFT 6
#define CS42L42_ASP_RX_CH_AP_MASK (1 << CS42L42_ASP_RX_CH_AP_SHIFT)
#define CS42L42_ASP_RX_CH_AP_LOW 0
#define CS42L42_ASP_RX_CH_AP_HI 1
#define CS42L42_ASP_RX_CH_RES_SHIFT 0
#define CS42L42_ASP_RX_CH_RES_MASK (3 << CS42L42_ASP_RX_CH_RES_SHIFT)
#define CS42L42_ASP_RX_CH_RES_32 3
#define CS42L42_ASP_RX_CH_RES_16 1
#define CS42L42_ASP_RX_CH_BIT_ST_SHIFT 0
#define CS42L42_ASP_RX_CH_BIT_ST_MASK (0xff << CS42L42_ASP_RX_CH_BIT_ST_SHIFT)
/* Page 0x30 ID Registers */
#define CS42L42_SUB_REVID (CS42L42_PAGE_30 + 0x14)
#define CS42L42_MAX_REGISTER (CS42L42_PAGE_30 + 0x14)
/* Defines for fracturing values spread across multiple registers */
#define CS42L42_FRAC0_VAL(val) ((val) & 0x0000ff)
#define CS42L42_FRAC1_VAL(val) (((val) & 0x00ff00) >> 8)
#define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16)
#define CS42L42_NUM_SUPPLIES 5
#define CS42L42_BOOT_TIME_US 3000
#define CS42L42_PLL_DIVOUT_TIME_US 800
#define CS42L42_CLOCK_SWITCH_DELAY_US 150
#define CS42L42_PLL_LOCK_POLL_US 250
#define CS42L42_PLL_LOCK_TIMEOUT_US 1250
#define CS42L42_HP_ADC_EN_TIME_US 20000
#define CS42L42_PDN_DONE_POLL_US 1000
#define CS42L42_PDN_DONE_TIMEOUT_US 200000
#define CS42L42_PDN_DONE_TIME_MS 100
#define CS42L42_FILT_DISCHARGE_TIME_MS 46
#endif /* __CS42L42_H */

View File

@ -59,6 +59,9 @@ struct hda_bus {
unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
unsigned int bus_probing :1; /* during probing process */
unsigned int keep_power:1; /* keep power up for notification */
unsigned int jackpoll_in_suspend:1; /* keep jack polling during
* runtime suspend
*/
int primary_dig_out_type; /* primary digital out PCM type */
unsigned int mixer_assigned; /* codec addr for mixer name */

View File

@ -15,7 +15,8 @@ enum {
SND_INTEL_DSP_DRIVER_LEGACY,
SND_INTEL_DSP_DRIVER_SST,
SND_INTEL_DSP_DRIVER_SOF,
SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_SOF
SND_INTEL_DSP_DRIVER_AVS,
SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_AVS
};
#if IS_ENABLED(CONFIG_SND_INTEL_DSP_CONFIG)

View File

@ -25,8 +25,6 @@ enum nhlt_device_type {
NHLT_DEVICE_INVALID
};
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
struct wav_fmt {
u16 fmt_tag;
u16 channels;
@ -126,6 +124,8 @@ enum {
NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf,
};
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
struct nhlt_acpi_table *intel_nhlt_init(struct device *dev);
void intel_nhlt_free(struct nhlt_acpi_table *addr);
@ -143,8 +143,6 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
#else
struct nhlt_acpi_table;
static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
{
return NULL;

View File

@ -62,6 +62,7 @@ struct snd_jack {
const char *id;
#ifdef CONFIG_SND_JACK_INPUT_DEV
struct input_dev *input_dev;
struct mutex input_dev_lock;
int registered;
int type;
char name[100];

View File

@ -156,6 +156,7 @@ struct snd_soc_acpi_link_adr {
* @links: array of link _ADR descriptors, null terminated.
* @drv_name: machine driver name
* @fw_filename: firmware file name. Used when SOF is not enabled.
* @tplg_filename: topology file name. Used when SOF is not enabled.
* @board: board name
* @machine_quirk: pointer to quirk, usually based on DMI information when
* ACPI ID alone is not sufficient, wrong or misleading
@ -174,6 +175,7 @@ struct snd_soc_acpi_mach {
const struct snd_soc_acpi_link_adr *links;
const char *drv_name;
const char *fw_filename;
const char *tplg_filename;
const char *board;
struct snd_soc_acpi_mach * (*machine_quirk)(void *arg);
const void *quirk_data;

View File

@ -16,8 +16,11 @@ enum snd_soc_card_subclass {
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
const char *name);
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack,
struct snd_soc_jack_pin *pins, unsigned int num_pins);
struct snd_soc_jack *jack);
int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id,
int type, struct snd_soc_jack *jack,
struct snd_soc_jack_pin *pins,
unsigned int num_pins);
int snd_soc_card_suspend_pre(struct snd_soc_card *card);
int snd_soc_card_suspend_post(struct snd_soc_card *card);

View File

@ -169,6 +169,15 @@ struct snd_soc_component_driver {
unsigned int idle_bias_on:1;
unsigned int suspend_bias_off:1;
unsigned int use_pmdown_time:1; /* care pmdown_time at stop */
/*
* Indicates that the component does not care about the endianness of
* PCM audio data and the core will ensure that both LE and BE variants
* of each used format are present. Typically this is because the
* component sits behind a bus that abstracts away the endian of the
* original data, ie. one for which the transmission endian is defined
* (I2S/SLIMbus/SoundWire), or the concept of endian doesn't exist (PDM,
* analogue).
*/
unsigned int endianness:1;
unsigned int non_legacy_dai_naming:1;

View File

@ -103,6 +103,8 @@ struct snd_soc_dpcm_runtime {
int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
int be_start; /* refcount protected by BE stream pcm lock */
int be_pause; /* refcount protected by BE stream pcm lock */
bool fe_pause; /* used to track STOP after PAUSE */
};
#define for_each_dpcm_fe(be, stream, _dpcm) \

View File

@ -176,6 +176,8 @@
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \
xmin, xmax, xsign_bit, xinvert) }
#define SOC_SINGLE_S_TLV(xname, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \
SOC_DOUBLE_R_S_TLV(xname, xreg, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array)
#define SOC_SINGLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@ -280,6 +282,23 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
xmax, xinvert) }
#define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \
xsign_bit, xinvert, xhandler_get, xhandler_put, \
tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \
xmin, xmax, xsign_bit, xinvert) }
#define SOC_SINGLE_S_EXT_TLV(xname, xreg, xshift, xmin, xmax, \
xsign_bit, xinvert, xhandler_get, xhandler_put, \
tlv_array) \
SOC_DOUBLE_R_S_EXT_TLV(xname, xreg, xreg, xshift, xmin, xmax, \
xsign_bit, xinvert, xhandler_get, xhandler_put, \
tlv_array)
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_bool_ext, \
@ -485,6 +504,8 @@ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms);
int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params,
int tdm_width, int tdm_slots, int slot_multiple);
/* set runtime hw params */
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
@ -1238,7 +1259,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname);
unsigned int snd_soc_daifmt_clock_provider_fliped(unsigned int dai_fmt);
unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt);
unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame);
unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix);
@ -1263,6 +1284,10 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
struct device_node *of_node,
struct snd_soc_dai_link *dai_link);
void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link);
int snd_soc_of_get_dai_link_cpus(struct device *dev,
struct device_node *of_node,
struct snd_soc_dai_link *dai_link);
void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link);
int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);

View File

@ -16,6 +16,7 @@
#include <sound/soc-acpi.h>
struct snd_sof_dsp_ops;
struct snd_sof_dev;
/**
* enum sof_fw_state - DSP firmware state definitions
@ -47,6 +48,13 @@ enum sof_dsp_power_states {
SOF_DSP_PM_D3,
};
/* Definitions for multiple IPCs */
enum sof_ipc_type {
SOF_IPC,
SOF_INTEL_IPC4,
SOF_IPC_TYPE_COUNT
};
/*
* SOF Platform data.
*/
@ -83,6 +91,8 @@ struct snd_sof_pdata {
const struct snd_soc_acpi_mach *machine;
void *hw_pdata;
enum sof_ipc_type ipc_type;
};
/*
@ -115,14 +125,19 @@ struct sof_dev_desc {
/* defaults for no codec mode */
const char *nocodec_tplg_filename;
/* information on supported IPCs */
unsigned int ipc_supported_mask;
enum sof_ipc_type ipc_default;
/* defaults paths for firmware and topology files */
const char *default_fw_path;
const char *default_tplg_path;
const char *default_fw_path[SOF_IPC_TYPE_COUNT];
const char *default_tplg_path[SOF_IPC_TYPE_COUNT];
/* default firmware name */
const char *default_fw_filename;
const char *default_fw_filename[SOF_IPC_TYPE_COUNT];
const struct snd_sof_dsp_ops *ops;
struct snd_sof_dsp_ops *ops;
int (*ops_init)(struct snd_sof_dev *sdev);
};
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);

View File

@ -0,0 +1,119 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2022 Intel Corporation. All rights reserved.
*/
/*
* Extended manifest is a place to store metadata about firmware, known during
* compilation time - for example firmware version or used compiler.
* Given information are read on host side before firmware startup.
* This part of output binary is not signed.
*/
#ifndef __SOF_FIRMWARE_EXT_MANIFEST4_H__
#define __SOF_FIRMWARE_EXT_MANIFEST4_H__
#include <linux/uuid.h>
/* In ASCII $AE1 */
#define SOF_EXT_MAN4_MAGIC_NUMBER 0x31454124
#define MAX_MODULE_NAME_LEN 8
#define MAX_FW_BINARY_NAME 8
#define DEFAULT_HASH_SHA256_LEN 32
#define SOF_MAN4_FW_HDR_OFFSET 0x2000
#define SOF_MAN4_FW_HDR_OFFSET_CAVS_1_5 0x284
/*********************************************************************
* extended manifest (struct sof_ext_manifest4_hdr)
*-------------------
* css_manifest hdr
*-------------------
* offset reserved for future
*-------------------
* fw_hdr (struct sof_man4_fw_binary_header)
*-------------------
* module_entry[0] (struct sof_man4_module)
*-------------------
* module_entry[1]
*-------------------
* ...
*-------------------
* module_entry[n]
*-------------------
* module_config[0] (struct sof_man4_module_config)
*-------------------
* module_config[1]
*-------------------
* ...
*-------------------
* module_config[m]
*-------------------
* FW content
*-------------------
*********************************************************************/
struct sof_ext_manifest4_hdr {
uint32_t id;
uint32_t len; /* length of extension manifest */
uint16_t version_major; /* header version */
uint16_t version_minor;
uint32_t num_module_entries;
} __packed;
struct sof_man4_fw_binary_header {
/* This part must be unchanged to be backward compatible with SPT-LP ROM */
uint32_t id;
uint32_t len; /* sizeof(sof_man4_fw_binary_header) in bytes */
uint8_t name[MAX_FW_BINARY_NAME];
uint32_t preload_page_count; /* number of pages of preloaded image */
uint32_t fw_image_flags;
uint32_t feature_mask;
uint16_t major_version; /* Firmware version */
uint16_t minor_version;
uint16_t hotfix_version;
uint16_t build_version;
uint32_t num_module_entries;
/* This part may change to contain any additional data for BaseFw that is skipped by ROM */
uint32_t hw_buf_base_addr;
uint32_t hw_buf_length;
uint32_t load_offset; /* This value is used by ROM */
} __packed;
struct sof_man4_segment_desc {
uint32_t flags;
uint32_t v_base_addr;
uint32_t file_offset;
} __packed;
struct sof_man4_module {
uint32_t id;
uint8_t name[MAX_MODULE_NAME_LEN];
guid_t uuid;
uint32_t type;
uint8_t hash[DEFAULT_HASH_SHA256_LEN];
uint32_t entry_point;
uint16_t cfg_offset;
uint16_t cfg_count;
uint32_t affinity_mask;
uint16_t instance_max_count;
uint16_t instance_stack_size;
struct sof_man4_segment_desc segments[3];
} __packed;
struct sof_man4_module_config {
uint32_t par[4]; /* module parameters */
uint32_t is_bytes; /* actual size of instance .bss (bytes) */
uint32_t cps; /* cycles per second */
uint32_t ibs; /* input buffer size (bytes) */
uint32_t obs; /* output buffer size (bytes) */
uint32_t module_flags; /* flags, reserved for future use */
uint32_t cpc; /* cycles per single run */
uint32_t obls; /* output block size, reserved for future use */
} __packed;
#endif /* __SOF_FIRMWARE_EXT_MANIFEST4_H__ */

View File

@ -0,0 +1,460 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2022 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_SOUND_SOF_IPC4_HEADER_H__
#define __INCLUDE_SOUND_SOF_IPC4_HEADER_H__
#include <linux/types.h>
#include <uapi/sound/sof/abi.h>
/* maximum message size for mailbox Tx/Rx */
#define SOF_IPC4_MSG_MAX_SIZE 4096
/** \addtogroup sof_uapi uAPI
* SOF uAPI specification.
* @{
*/
/**
* struct sof_ipc4_msg - Placeholder of an IPC4 message
* @header_u64: IPC4 header as single u64 number
* @primary: Primary, mandatory part of the header
* @extension: Extended part of the header, if not used it should be
* set to 0
* @data_size: Size of data in bytes pointed by @data_ptr
* @data_ptr: Pointer to the optional payload of a message
*/
struct sof_ipc4_msg {
union {
u64 header_u64;
struct {
u32 primary;
u32 extension;
};
};
size_t data_size;
void *data_ptr;
};
/**
* struct sof_ipc4_tuple - Generic type/ID and parameter tuple
* @type: type/ID
* @size: size of the @value array in bytes
* @value: value for the given type
*/
struct sof_ipc4_tuple {
uint32_t type;
uint32_t size;
uint32_t value[];
} __packed;
/*
* IPC4 messages have two 32 bit identifier made up as follows :-
*
* header - msg type, msg id, msg direction ...
* extension - extra params such as msg data size in mailbox
*
* These are sent at the start of the IPC message in the mailbox. Messages
* should not be sent in the doorbell (special exceptions for firmware).
*/
/*
* IPC4 primary header bit allocation for messages
* bit 0-23: message type specific
* bit 24-28: type: enum sof_ipc4_global_msg if target is SOF_IPC4_FW_GEN_MSG
* enum sof_ipc4_module_type if target is SOF_IPC4_MODULE_MSG
* bit 29: response - sof_ipc4_msg_dir
* bit 30: target - enum sof_ipc4_msg_target
* bit 31: reserved, unused
*/
/* Value of target field - must fit into 1 bit */
enum sof_ipc4_msg_target {
/* Global FW message */
SOF_IPC4_FW_GEN_MSG,
/* Module message */
SOF_IPC4_MODULE_MSG
};
/* Value of type field - must fit into 5 bits */
enum sof_ipc4_global_msg {
SOF_IPC4_GLB_BOOT_CONFIG,
SOF_IPC4_GLB_ROM_CONTROL,
SOF_IPC4_GLB_IPCGATEWAY_CMD,
/* 3 .. 12: RESERVED - do not use */
SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD = 13,
SOF_IPC4_GLB_CHAIN_DMA,
SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES,
SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES,
/* pipeline settings */
SOF_IPC4_GLB_CREATE_PIPELINE,
SOF_IPC4_GLB_DELETE_PIPELINE,
SOF_IPC4_GLB_SET_PIPELINE_STATE,
SOF_IPC4_GLB_GET_PIPELINE_STATE,
SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE,
SOF_IPC4_GLB_SAVE_PIPELINE,
SOF_IPC4_GLB_RESTORE_PIPELINE,
/* Loads library (using Code Load or HD/A Host Output DMA) */
SOF_IPC4_GLB_LOAD_LIBRARY,
/* 25: RESERVED - do not use */
SOF_IPC4_GLB_INTERNAL_MESSAGE = 26,
/* Notification (FW to SW driver) */
SOF_IPC4_GLB_NOTIFICATION,
/* 28 .. 31: RESERVED - do not use */
SOF_IPC4_GLB_TYPE_LAST,
};
/* Value of response field - must fit into 1 bit */
enum sof_ipc4_msg_dir {
SOF_IPC4_MSG_REQUEST,
SOF_IPC4_MSG_REPLY,
};
enum sof_ipc4_pipeline_state {
SOF_IPC4_PIPE_INVALID_STATE,
SOF_IPC4_PIPE_UNINITIALIZED,
SOF_IPC4_PIPE_RESET,
SOF_IPC4_PIPE_PAUSED,
SOF_IPC4_PIPE_RUNNING,
SOF_IPC4_PIPE_EOS
};
/* Generic message fields (bit 24-30) */
/* encoded to header's msg_tgt field */
#define SOF_IPC4_MSG_TARGET_SHIFT 30
#define SOF_IPC4_MSG_TARGET_MASK BIT(30)
#define SOF_IPC4_MSG_TARGET(x) ((x) << SOF_IPC4_MSG_TARGET_SHIFT)
#define SOF_IPC4_MSG_IS_MODULE_MSG(x) ((x) & SOF_IPC4_MSG_TARGET_MASK ? 1 : 0)
/* encoded to header's rsp field */
#define SOF_IPC4_MSG_DIR_SHIFT 29
#define SOF_IPC4_MSG_DIR_MASK BIT(29)
#define SOF_IPC4_MSG_DIR(x) ((x) << SOF_IPC4_MSG_DIR_SHIFT)
/* encoded to header's type field */
#define SOF_IPC4_MSG_TYPE_SHIFT 24
#define SOF_IPC4_MSG_TYPE_MASK GENMASK(28, 24)
#define SOF_IPC4_MSG_TYPE_SET(x) (((x) << SOF_IPC4_MSG_TYPE_SHIFT) & \
SOF_IPC4_MSG_TYPE_MASK)
#define SOF_IPC4_MSG_TYPE_GET(x) (((x) & SOF_IPC4_MSG_TYPE_MASK) >> \
SOF_IPC4_MSG_TYPE_SHIFT)
/* Global message type specific field definitions */
/* pipeline creation ipc msg */
#define SOF_IPC4_GLB_PIPE_INSTANCE_SHIFT 16
#define SOF_IPC4_GLB_PIPE_INSTANCE_MASK GENMASK(23, 16)
#define SOF_IPC4_GLB_PIPE_INSTANCE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_INSTANCE_SHIFT)
#define SOF_IPC4_GLB_PIPE_PRIORITY_SHIFT 11
#define SOF_IPC4_GLB_PIPE_PRIORITY_MASK GENMASK(15, 11)
#define SOF_IPC4_GLB_PIPE_PRIORITY(x) ((x) << SOF_IPC4_GLB_PIPE_PRIORITY_SHIFT)
#define SOF_IPC4_GLB_PIPE_MEM_SIZE_SHIFT 0
#define SOF_IPC4_GLB_PIPE_MEM_SIZE_MASK GENMASK(10, 0)
#define SOF_IPC4_GLB_PIPE_MEM_SIZE(x) ((x) << SOF_IPC4_GLB_PIPE_MEM_SIZE_SHIFT)
#define SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT 0
#define SOF_IPC4_GLB_PIPE_EXT_LP_MASK BIT(0)
#define SOF_IPC4_GLB_PIPE_EXT_LP(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT)
/* pipeline set state ipc msg */
#define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16
#define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16)
#define SOF_IPC4_GLB_PIPE_STATE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT)
#define SOF_IPC4_GLB_PIPE_STATE_SHIFT 0
#define SOF_IPC4_GLB_PIPE_STATE_MASK GENMASK(15, 0)
#define SOF_IPC4_GLB_PIPE_STATE(x) ((x) << SOF_IPC4_GLB_PIPE_STATE_SHIFT)
enum sof_ipc4_channel_config {
/* one channel only. */
SOF_IPC4_CHANNEL_CONFIG_MONO,
/* L & R. */
SOF_IPC4_CHANNEL_CONFIG_STEREO,
/* L, R & LFE; PCM only. */
SOF_IPC4_CHANNEL_CONFIG_2_POINT_1,
/* L, C & R; MP3 & AAC only. */
SOF_IPC4_CHANNEL_CONFIG_3_POINT_0,
/* L, C, R & LFE; PCM only. */
SOF_IPC4_CHANNEL_CONFIG_3_POINT_1,
/* L, R, Ls & Rs; PCM only. */
SOF_IPC4_CHANNEL_CONFIG_QUATRO,
/* L, C, R & Cs; MP3 & AAC only. */
SOF_IPC4_CHANNEL_CONFIG_4_POINT_0,
/* L, C, R, Ls & Rs. */
SOF_IPC4_CHANNEL_CONFIG_5_POINT_0,
/* L, C, R, Ls, Rs & LFE. */
SOF_IPC4_CHANNEL_CONFIG_5_POINT_1,
/* one channel replicated in two. */
SOF_IPC4_CHANNEL_CONFIG_DUAL_MONO,
/* Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] */
SOF_IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0,
/* Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] */
SOF_IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1,
/* L, C, R, Ls, Rs & LFE., LS, RS */
SOF_IPC4_CHANNEL_CONFIG_7_POINT_1,
};
enum sof_ipc4_interleaved_style {
SOF_IPC4_CHANNELS_INTERLEAVED,
SOF_IPC4_CHANNELS_NONINTERLEAVED,
};
enum sof_ipc4_sample_type {
SOF_IPC4_MSB_INTEGER, /* integer with Most Significant Byte first */
SOF_IPC4_LSB_INTEGER, /* integer with Least Significant Byte first */
};
struct sof_ipc4_audio_format {
uint32_t sampling_frequency;
uint32_t bit_depth;
uint32_t ch_map;
uint32_t ch_cfg; /* sof_ipc4_channel_config */
uint32_t interleaving_style;
uint32_t fmt_cfg; /* channels_count valid_bit_depth s_type */
} __packed __aligned(4);
#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_SHIFT 0
#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_MASK GENMASK(7, 0)
#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(x) \
((x) & SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_MASK)
#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_SHIFT 8
#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_MASK GENMASK(15, 8)
#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(x) \
(((x) & SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_MASK) >> \
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_SHIFT)
#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_SHIFT 16
#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_MASK GENMASK(23, 16)
#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(x) \
(((x) & SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_MASK) >> \
SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_SHIFT)
/* Module message type specific field definitions */
enum sof_ipc4_module_type {
SOF_IPC4_MOD_INIT_INSTANCE,
SOF_IPC4_MOD_CONFIG_GET,
SOF_IPC4_MOD_CONFIG_SET,
SOF_IPC4_MOD_LARGE_CONFIG_GET,
SOF_IPC4_MOD_LARGE_CONFIG_SET,
SOF_IPC4_MOD_BIND,
SOF_IPC4_MOD_UNBIND,
SOF_IPC4_MOD_SET_DX,
SOF_IPC4_MOD_SET_D0IX,
SOF_IPC4_MOD_ENTER_MODULE_RESTORE,
SOF_IPC4_MOD_EXIT_MODULE_RESTORE,
SOF_IPC4_MOD_DELETE_INSTANCE,
SOF_IPC4_MOD_TYPE_LAST,
};
struct sof_ipc4_base_module_cfg {
uint32_t cpc; /* the max count of Cycles Per Chunk processing */
uint32_t ibs; /* input Buffer Size (in bytes) */
uint32_t obs; /* output Buffer Size (in bytes) */
uint32_t is_pages; /* number of physical pages used */
struct sof_ipc4_audio_format audio_fmt;
} __packed __aligned(4);
/* common module ipc msg */
#define SOF_IPC4_MOD_INSTANCE_SHIFT 16
#define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16)
#define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT)
#define SOF_IPC4_MOD_ID_SHIFT 0
#define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0)
#define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT)
/* init module ipc msg */
#define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0
#define SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK GENMASK(15, 0)
#define SOF_IPC4_MOD_EXT_PARAM_SIZE(x) ((x) << SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT)
#define SOF_IPC4_MOD_EXT_PPL_ID_SHIFT 16
#define SOF_IPC4_MOD_EXT_PPL_ID_MASK GENMASK(23, 16)
#define SOF_IPC4_MOD_EXT_PPL_ID(x) ((x) << SOF_IPC4_MOD_EXT_PPL_ID_SHIFT)
#define SOF_IPC4_MOD_EXT_CORE_ID_SHIFT 24
#define SOF_IPC4_MOD_EXT_CORE_ID_MASK GENMASK(27, 24)
#define SOF_IPC4_MOD_EXT_CORE_ID(x) ((x) << SOF_IPC4_MOD_EXT_CORE_ID_SHIFT)
#define SOF_IPC4_MOD_EXT_DOMAIN_SHIFT 28
#define SOF_IPC4_MOD_EXT_DOMAIN_MASK BIT(28)
#define SOF_IPC4_MOD_EXT_DOMAIN(x) ((x) << SOF_IPC4_MOD_EXT_DOMAIN_SHIFT)
/* bind/unbind module ipc msg */
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT 0
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_MASK GENMASK(15, 0)
#define SOF_IPC4_MOD_EXT_DST_MOD_ID(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT)
#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_SHIFT 16
#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_MASK GENMASK(23, 16)
#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_SHIFT)
#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_SHIFT 24
#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_MASK GENMASK(26, 24)
#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_SHIFT)
#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_SHIFT 27
#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_MASK GENMASK(29, 27)
#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(x) ((x) << SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_SHIFT)
#define MOD_ENABLE_LOG 6
#define MOD_SYSTEM_TIME 20
/* set module large config */
#define SOF_IPC4_MOD_EXT_MSG_SIZE_SHIFT 0
#define SOF_IPC4_MOD_EXT_MSG_SIZE_MASK GENMASK(19, 0)
#define SOF_IPC4_MOD_EXT_MSG_SIZE(x) ((x) << SOF_IPC4_MOD_EXT_MSG_SIZE_SHIFT)
#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT 20
#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK GENMASK(27, 20)
#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID(x) ((x) << SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT)
#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_SHIFT 28
#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_MASK BIT(28)
#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK(x) ((x) << SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_SHIFT)
#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_SHIFT 29
#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_MASK BIT(29)
#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(x) ((x) << SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_SHIFT)
/* Init instance messagees */
#define SOF_IPC4_MOD_INIT_BASEFW_MOD_ID 0
#define SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID 0
enum sof_ipc4_base_fw_params {
SOF_IPC4_FW_PARAM_ENABLE_LOGS = 6,
SOF_IPC4_FW_PARAM_FW_CONFIG,
SOF_IPC4_FW_PARAM_HW_CONFIG_GET,
SOF_IPC4_FW_PARAM_MODULES_INFO_GET,
SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16,
SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20,
};
enum sof_ipc4_fw_config_params {
SOF_IPC4_FW_CFG_FW_VERSION,
SOF_IPC4_FW_CFG_MEMORY_RECLAIMED,
SOF_IPC4_FW_CFG_SLOW_CLOCK_FREQ_HZ,
SOF_IPC4_FW_CFG_FAST_CLOCK_FREQ_HZ,
SOF_IPC4_FW_CFG_DMA_BUFFER_CONFIG,
SOF_IPC4_FW_CFG_ALH_SUPPORT_LEVEL,
SOF_IPC4_FW_CFG_DL_MAILBOX_BYTES,
SOF_IPC4_FW_CFG_UL_MAILBOX_BYTES,
SOF_IPC4_FW_CFG_TRACE_LOG_BYTES,
SOF_IPC4_FW_CFG_MAX_PPL_COUNT,
SOF_IPC4_FW_CFG_MAX_ASTATE_COUNT,
SOF_IPC4_FW_CFG_MAX_MODULE_PIN_COUNT,
SOF_IPC4_FW_CFG_MODULES_COUNT,
SOF_IPC4_FW_CFG_MAX_MOD_INST_COUNT,
SOF_IPC4_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT,
SOF_IPC4_FW_CFG_LL_PRI_COUNT,
SOF_IPC4_FW_CFG_MAX_DP_TASKS_COUNT,
SOF_IPC4_FW_CFG_MAX_LIBS_COUNT,
SOF_IPC4_FW_CFG_SCHEDULER_CONFIG,
SOF_IPC4_FW_CFG_XTAL_FREQ_HZ,
SOF_IPC4_FW_CFG_CLOCKS_CONFIG,
SOF_IPC4_FW_CFG_RESERVED,
SOF_IPC4_FW_CFG_POWER_GATING_POLICY,
SOF_IPC4_FW_CFG_ASSERT_MODE,
};
struct sof_ipc4_fw_version {
uint16_t major;
uint16_t minor;
uint16_t hotfix;
uint16_t build;
} __packed;
/* Reply messages */
/*
* IPC4 primary header bit allocation for replies
* bit 0-23: status
* bit 24-28: type: enum sof_ipc4_global_msg if target is SOF_IPC4_FW_GEN_MSG
* enum sof_ipc4_module_type if target is SOF_IPC4_MODULE_MSG
* bit 29: response - sof_ipc4_msg_dir
* bit 30: target - enum sof_ipc4_msg_target
* bit 31: reserved, unused
*/
#define SOF_IPC4_REPLY_STATUS GENMASK(23, 0)
/* Notification messages */
/*
* IPC4 primary header bit allocation for notifications
* bit 0-15: notification type specific
* bit 16-23: enum sof_ipc4_notification_type
* bit 24-28: SOF_IPC4_GLB_NOTIFICATION
* bit 29: response - sof_ipc4_msg_dir
* bit 30: target - enum sof_ipc4_msg_target
* bit 31: reserved, unused
*/
#define SOF_IPC4_MSG_IS_NOTIFICATION(x) (SOF_IPC4_MSG_TYPE_GET(x) == \
SOF_IPC4_GLB_NOTIFICATION)
#define SOF_IPC4_NOTIFICATION_TYPE_SHIFT 16
#define SOF_IPC4_NOTIFICATION_TYPE_MASK GENMASK(23, 16)
#define SOF_IPC4_NOTIFICATION_TYPE_GET(x) (((x) & SOF_IPC4_NOTIFICATION_TYPE_MASK) >> \
SOF_IPC4_NOTIFICATION_TYPE_SHIFT)
/* Value of notification type field - must fit into 8 bits */
enum sof_ipc4_notification_type {
/* Phrase detected (notification from WoV module) */
SOF_IPC4_NOTIFY_PHRASE_DETECTED = 4,
/* Event from a resource (pipeline or module instance) */
SOF_IPC4_NOTIFY_RESOURCE_EVENT,
/* Debug log buffer status changed */
SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS,
/* Timestamp captured at the link */
SOF_IPC4_NOTIFY_TIMESTAMP_CAPTURED,
/* FW complete initialization */
SOF_IPC4_NOTIFY_FW_READY,
/* Audio classifier result (ACA) */
SOF_IPC4_NOTIFY_FW_AUD_CLASS_RESULT,
/* Exception caught by DSP FW */
SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT,
/* 11 is skipped by the existing cavs firmware */
/* Custom module notification */
SOF_IPC4_NOTIFY_MODULE_NOTIFICATION = 12,
/* 13 is reserved - do not use */
/* Probe notify data available */
SOF_IPC4_NOTIFY_PROBE_DATA_AVAILABLE = 14,
/* AM module notifications */
SOF_IPC4_NOTIFY_ASYNC_MSG_SRVC_MESSAGE,
SOF_IPC4_NOTIFY_TYPE_LAST,
};
struct sof_ipc4_notify_resource_data {
uint32_t resource_type;
uint32_t resource_id;
uint32_t event_type;
uint32_t reserved;
uint32_t data[6];
} __packed __aligned(4);
/** @}*/
#endif

View File

@ -85,8 +85,9 @@ struct sof_ipc_stream_params {
uint32_t host_period_bytes;
uint16_t no_stream_position; /**< 1 means don't send stream position */
uint8_t cont_update_posn; /**< 1 means continuous update stream position */
uint16_t reserved[3];
uint8_t reserved[5];
uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */
} __packed;

View File

@ -0,0 +1,126 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright(c) 2021 Intel Corporation. All rights reserved.
*
* Authors: Cezary Rojewski <cezary.rojewski@intel.com>
* Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
*/
#ifndef __UAPI_SOUND_INTEL_AVS_TOKENS_H
#define __UAPI_SOUND_INTEL_AVS_TOKENS_H
enum avs_tplg_token {
/* struct avs_tplg */
AVS_TKN_MANIFEST_NAME_STRING = 1,
AVS_TKN_MANIFEST_VERSION_U32 = 2,
AVS_TKN_MANIFEST_NUM_LIBRARIES_U32 = 3,
AVS_TKN_MANIFEST_NUM_AFMTS_U32 = 4,
AVS_TKN_MANIFEST_NUM_MODCFGS_BASE_U32 = 5,
AVS_TKN_MANIFEST_NUM_MODCFGS_EXT_U32 = 6,
AVS_TKN_MANIFEST_NUM_PPLCFGS_U32 = 7,
AVS_TKN_MANIFEST_NUM_BINDINGS_U32 = 8,
/* struct avs_tplg_library */
AVS_TKN_LIBRARY_ID_U32 = 101,
AVS_TKN_LIBRARY_NAME_STRING = 102,
/* struct avs_audio_format */
AVS_TKN_AFMT_ID_U32 = 201,
AVS_TKN_AFMT_SAMPLE_RATE_U32 = 202,
AVS_TKN_AFMT_BIT_DEPTH_U32 = 203,
AVS_TKN_AFMT_CHANNEL_MAP_U32 = 204,
AVS_TKN_AFMT_CHANNEL_CFG_U32 = 205,
AVS_TKN_AFMT_INTERLEAVING_U32 = 206,
AVS_TKN_AFMT_NUM_CHANNELS_U32 = 207,
AVS_TKN_AFMT_VALID_BIT_DEPTH_U32 = 208,
AVS_TKN_AFMT_SAMPLE_TYPE_U32 = 209,
/* struct avs_tplg_modcfg_base */
AVS_TKN_MODCFG_BASE_ID_U32 = 301,
AVS_TKN_MODCFG_BASE_CPC_U32 = 302,
AVS_TKN_MODCFG_BASE_IBS_U32 = 303,
AVS_TKN_MODCFG_BASE_OBS_U32 = 304,
AVS_TKN_MODCFG_BASE_PAGES_U32 = 305,
/* struct avs_tplg_modcfg_ext */
AVS_TKN_MODCFG_EXT_ID_U32 = 401,
AVS_TKN_MODCFG_EXT_TYPE_UUID = 402,
AVS_TKN_MODCFG_CPR_OUT_AFMT_ID_U32 = 403,
AVS_TKN_MODCFG_CPR_FEATURE_MASK_U32 = 404,
AVS_TKN_MODCFG_CPR_DMA_TYPE_U32 = 405,
AVS_TKN_MODCFG_CPR_DMABUFF_SIZE_U32 = 406,
AVS_TKN_MODCFG_CPR_VINDEX_U8 = 407,
AVS_TKN_MODCFG_CPR_BLOB_FMT_ID_U32 = 408,
AVS_TKN_MODCFG_MICSEL_OUT_AFMT_ID_U32 = 409,
AVS_TKN_MODCFG_INTELWOV_CPC_LP_MODE_U32 = 410,
AVS_TKN_MODCFG_SRC_OUT_FREQ_U32 = 411,
AVS_TKN_MODCFG_MUX_REF_AFMT_ID_U32 = 412,
AVS_TKN_MODCFG_MUX_OUT_AFMT_ID_U32 = 413,
AVS_TKN_MODCFG_AEC_REF_AFMT_ID_U32 = 414,
AVS_TKN_MODCFG_AEC_OUT_AFMT_ID_U32 = 415,
AVS_TKN_MODCFG_AEC_CPC_LP_MODE_U32 = 416,
AVS_TKN_MODCFG_ASRC_OUT_FREQ_U32 = 417,
AVS_TKN_MODCFG_ASRC_MODE_U8 = 418,
AVS_TKN_MODCFG_ASRC_DISABLE_JITTER_U8 = 419,
AVS_TKN_MODCFG_UPDOWN_MIX_OUT_CHAN_CFG_U32 = 420,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_SELECT_U32 = 421,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_0_S32 = 422,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_1_S32 = 423,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_2_S32 = 424,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_3_S32 = 425,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_4_S32 = 426,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_5_S32 = 427,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_6_S32 = 428,
AVS_TKN_MODCFG_UPDOWN_MIX_COEFF_7_S32 = 429,
AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32 = 430,
AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16 = 431,
AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16 = 432,
/* struct avs_tplg_pplcfg */
AVS_TKN_PPLCFG_ID_U32 = 1401,
AVS_TKN_PPLCFG_REQ_SIZE_U16 = 1402,
AVS_TKN_PPLCFG_PRIORITY_U8 = 1403,
AVS_TKN_PPLCFG_LOW_POWER_BOOL = 1404,
AVS_TKN_PPLCFG_ATTRIBUTES_U16 = 1405,
AVS_TKN_PPLCFG_TRIGGER_U32 = 1406,
/* struct avs_tplg_binding */
AVS_TKN_BINDING_ID_U32 = 1501,
AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING = 1502,
AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32 = 1503,
AVS_TKN_BINDING_TARGET_PPL_ID_U32 = 1504,
AVS_TKN_BINDING_TARGET_MOD_ID_U32 = 1505,
AVS_TKN_BINDING_TARGET_MOD_PIN_U8 = 1506,
AVS_TKN_BINDING_MOD_ID_U32 = 1507,
AVS_TKN_BINDING_MOD_PIN_U8 = 1508,
AVS_TKN_BINDING_IS_SINK_U8 = 1509,
/* struct avs_tplg_pipeline */
AVS_TKN_PPL_ID_U32 = 1601,
AVS_TKN_PPL_PPLCFG_ID_U32 = 1602,
AVS_TKN_PPL_NUM_BINDING_IDS_U32 = 1603,
AVS_TKN_PPL_BINDING_ID_U32 = 1604,
/* struct avs_tplg_module */
AVS_TKN_MOD_ID_U32 = 1701,
AVS_TKN_MOD_MODCFG_BASE_ID_U32 = 1702,
AVS_TKN_MOD_IN_AFMT_ID_U32 = 1703,
AVS_TKN_MOD_CORE_ID_U8 = 1704,
AVS_TKN_MOD_PROC_DOMAIN_U8 = 1705,
AVS_TKN_MOD_MODCFG_EXT_ID_U32 = 1706,
/* struct avs_tplg_path_template */
AVS_TKN_PATH_TMPL_ID_U32 = 1801,
/* struct avs_tplg_path */
AVS_TKN_PATH_ID_U32 = 1901,
AVS_TKN_PATH_FE_FMT_ID_U32 = 1902,
AVS_TKN_PATH_BE_FMT_ID_U32 = 1903,
/* struct avs_tplg_pin_format */
AVS_TKN_PIN_FMT_INDEX_U32 = 2201,
AVS_TKN_PIN_FMT_IOBS_U32 = 2202,
AVS_TKN_PIN_FMT_AFMT_ID_U32 = 2203,
};
#endif

View File

@ -26,8 +26,8 @@
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 19
#define SOF_ABI_PATCH 1
#define SOF_ABI_MINOR 21
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
#define SOF_ABI_MAJOR_SHIFT 24

View File

@ -42,8 +42,11 @@ static int snd_jack_dev_disconnect(struct snd_device *device)
#ifdef CONFIG_SND_JACK_INPUT_DEV
struct snd_jack *jack = device->device_data;
if (!jack->input_dev)
mutex_lock(&jack->input_dev_lock);
if (!jack->input_dev) {
mutex_unlock(&jack->input_dev_lock);
return 0;
}
/* If the input device is registered with the input subsystem
* then we need to use a different deallocator. */
@ -52,6 +55,7 @@ static int snd_jack_dev_disconnect(struct snd_device *device)
else
input_free_device(jack->input_dev);
jack->input_dev = NULL;
mutex_unlock(&jack->input_dev_lock);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
return 0;
}
@ -90,8 +94,11 @@ static int snd_jack_dev_register(struct snd_device *device)
snprintf(jack->name, sizeof(jack->name), "%s %s",
card->shortname, jack->id);
if (!jack->input_dev)
mutex_lock(&jack->input_dev_lock);
if (!jack->input_dev) {
mutex_unlock(&jack->input_dev_lock);
return 0;
}
jack->input_dev->name = jack->name;
@ -116,6 +123,7 @@ static int snd_jack_dev_register(struct snd_device *device)
if (err == 0)
jack->registered = 1;
mutex_unlock(&jack->input_dev_lock);
return err;
}
#endif /* CONFIG_SND_JACK_INPUT_DEV */
@ -517,9 +525,11 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
return -ENOMEM;
}
/* don't creat input device for phantom jack */
if (!phantom_jack) {
#ifdef CONFIG_SND_JACK_INPUT_DEV
mutex_init(&jack->input_dev_lock);
/* don't create input device for phantom jack */
if (!phantom_jack) {
int i;
jack->input_dev = input_allocate_device();
@ -537,8 +547,8 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
input_set_capability(jack->input_dev, EV_SW,
jack_switch_types[i]);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
}
#endif /* CONFIG_SND_JACK_INPUT_DEV */
err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
if (err < 0)
@ -578,10 +588,14 @@ EXPORT_SYMBOL(snd_jack_new);
void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
{
WARN_ON(jack->registered);
if (!jack->input_dev)
mutex_lock(&jack->input_dev_lock);
if (!jack->input_dev) {
mutex_unlock(&jack->input_dev_lock);
return;
}
jack->input_dev->dev.parent = parent;
mutex_unlock(&jack->input_dev_lock);
}
EXPORT_SYMBOL(snd_jack_set_parent);
@ -629,6 +643,8 @@ EXPORT_SYMBOL(snd_jack_set_key);
/**
* snd_jack_report - Report the current status of a jack
* Note: This function uses mutexes and should be called from a
* context which can sleep (such as a workqueue).
*
* @jack: The jack to report status for
* @status: The current status of the jack
@ -654,8 +670,11 @@ void snd_jack_report(struct snd_jack *jack, int status)
status & jack_kctl->mask_bits);
#ifdef CONFIG_SND_JACK_INPUT_DEV
if (!jack->input_dev)
mutex_lock(&jack->input_dev_lock);
if (!jack->input_dev) {
mutex_unlock(&jack->input_dev_lock);
return;
}
for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits);
@ -675,6 +694,7 @@ void snd_jack_report(struct snd_jack *jack, int status)
}
input_sync(jack->input_dev);
mutex_unlock(&jack->input_dev_lock);
#endif /* CONFIG_SND_JACK_INPUT_DEV */
}
EXPORT_SYMBOL(snd_jack_report);

View File

@ -453,7 +453,6 @@ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
*/
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
{
struct snd_card *card = substream->pcm->card;
struct snd_pcm_runtime *runtime;
if (PCM_RUNTIME_CHECK(substream))
@ -462,6 +461,8 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
if (runtime->dma_area == NULL)
return 0;
if (runtime->dma_buffer_p != &substream->dma_buffer) {
struct snd_card *card = substream->pcm->card;
/* it's a newly allocated buffer. release it now. */
do_free_pages(card, runtime->dma_buffer_p);
kfree(runtime->dma_buffer_p);

View File

@ -139,7 +139,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
port_subs_info_init(&new_port->c_dest);
snd_use_lock_use(&new_port->use_lock);
num = port >= 0 ? port : 0;
num = max(port, 0);
mutex_lock(&client->ports_mutex);
write_lock_irq(&client->ports_lock);
list_for_each_entry(p, &client->ports_list_head, list) {

View File

@ -165,6 +165,24 @@ config SND_SERIAL_U16550
To compile this driver as a module, choose M here: the module
will be called snd-serial-u16550.
config SND_SERIAL_GENERIC
tristate "Generic serial MIDI driver"
depends on SERIAL_DEV_BUS
depends on OF
select SND_RAWMIDI
help
To include support for mapping generic serial devices as raw
ALSA MIDI devices, say Y here. The driver only supports setting
the serial port to standard baudrates. To attain the standard MIDI
baudrate of 31.25 kBaud, configure the clock of the underlying serial
device so that a requested 38.4 kBaud will result in the standard speed.
Use this devicetree binding to configure serial port mapping
<file:Documentation/devicetree/bindings/sound/serial-midi.yaml>
To compile this driver as a module, choose M here: the module
will be called snd-serial-generic.
config SND_MPU401
tristate "Generic MPU-401 UART driver"
select SND_MPU401_UART

View File

@ -10,6 +10,7 @@ snd-mtpav-objs := mtpav.o
snd-mts64-objs := mts64.o
snd-portman2x4-objs := portman2x4.o
snd-serial-u16550-objs := serial-u16550.o
snd-serial-generic-objs := serial-generic.o
snd-virmidi-objs := virmidi.o
# Toplevel Module Dependency
@ -17,6 +18,7 @@ obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
obj-$(CONFIG_SND_ALOOP) += snd-aloop.o
obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
obj-$(CONFIG_SND_SERIAL_GENERIC) += snd-serial-generic.o
obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
obj-$(CONFIG_SND_MTS64) += snd-mts64.o
obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o

View File

@ -0,0 +1,374 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* serial-generic.c
* Copyright (c) by Daniel Kaehn <kaehndan@gmail.com
* Based on serial-u16550.c by Jaroslav Kysela <perex@perex.cz>,
* Isaku Yamahata <yamahata@private.email.ne.jp>,
* George Hansper <ghansper@apana.org.au>,
* Hannu Savolainen
*
* Generic serial MIDI driver using the serdev serial bus API for hardware interaction
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/serdev.h>
#include <linux/serial_reg.h>
#include <linux/slab.h>
#include <linux/dev_printk.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <sound/initval.h>
MODULE_DESCRIPTION("Generic serial MIDI driver");
MODULE_LICENSE("GPL");
#define SERIAL_MODE_INPUT_OPEN 1
#define SERIAL_MODE_OUTPUT_OPEN 2
#define SERIAL_MODE_INPUT_TRIGGERED 3
#define SERIAL_MODE_OUTPUT_TRIGGERED 4
#define SERIAL_TX_STATE_ACTIVE 1
#define SERIAL_TX_STATE_WAKEUP 2
struct snd_serial_generic {
struct serdev_device *serdev;
struct snd_card *card;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *midi_output;
struct snd_rawmidi_substream *midi_input;
unsigned int baudrate;
unsigned long filemode; /* open status of file */
struct work_struct tx_work;
unsigned long tx_state;
};
static void snd_serial_generic_tx_wakeup(struct snd_serial_generic *drvdata)
{
if (test_and_set_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state))
set_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state);
schedule_work(&drvdata->tx_work);
}
#define INTERNAL_BUF_SIZE 256
static void snd_serial_generic_tx_work(struct work_struct *work)
{
static char buf[INTERNAL_BUF_SIZE];
int num_bytes;
struct snd_serial_generic *drvdata = container_of(work, struct snd_serial_generic,
tx_work);
struct snd_rawmidi_substream *substream = drvdata->midi_output;
clear_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state);
while (!snd_rawmidi_transmit_empty(substream)) {
if (!test_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode))
break;
num_bytes = snd_rawmidi_transmit_peek(substream, buf, INTERNAL_BUF_SIZE);
num_bytes = serdev_device_write_buf(drvdata->serdev, buf, num_bytes);
if (!num_bytes)
break;
snd_rawmidi_transmit_ack(substream, num_bytes);
if (!test_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state))
break;
}
clear_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state);
}
static void snd_serial_generic_write_wakeup(struct serdev_device *serdev)
{
struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev);
snd_serial_generic_tx_wakeup(drvdata);
}
static int snd_serial_generic_receive_buf(struct serdev_device *serdev,
const unsigned char *buf, size_t count)
{
int ret;
struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev);
if (!test_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode))
return 0;
ret = snd_rawmidi_receive(drvdata->midi_input, buf, count);
return ret < 0 ? 0 : ret;
}
static const struct serdev_device_ops snd_serial_generic_serdev_device_ops = {
.receive_buf = snd_serial_generic_receive_buf,
.write_wakeup = snd_serial_generic_write_wakeup
};
static int snd_serial_generic_ensure_serdev_open(struct snd_serial_generic *drvdata)
{
int err;
unsigned int actual_baud;
if (drvdata->filemode)
return 0;
dev_dbg(drvdata->card->dev, "Opening serial port for card %s\n",
drvdata->card->shortname);
err = serdev_device_open(drvdata->serdev);
if (err < 0)
return err;
actual_baud = serdev_device_set_baudrate(drvdata->serdev,
drvdata->baudrate);
if (actual_baud != drvdata->baudrate) {
dev_warn(drvdata->card->dev, "requested %d baud for card %s but it was actually set to %d\n",
drvdata->baudrate, drvdata->card->shortname, actual_baud);
}
return 0;
}
static int snd_serial_generic_input_open(struct snd_rawmidi_substream *substream)
{
int err;
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
dev_dbg(drvdata->card->dev, "Opening input for card %s\n",
drvdata->card->shortname);
err = snd_serial_generic_ensure_serdev_open(drvdata);
if (err < 0)
return err;
set_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode);
drvdata->midi_input = substream;
return 0;
}
static int snd_serial_generic_input_close(struct snd_rawmidi_substream *substream)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
dev_dbg(drvdata->card->dev, "Closing input for card %s\n",
drvdata->card->shortname);
clear_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode);
clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
drvdata->midi_input = NULL;
if (!drvdata->filemode)
serdev_device_close(drvdata->serdev);
return 0;
}
static void snd_serial_generic_input_trigger(struct snd_rawmidi_substream *substream,
int up)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
if (up)
set_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
else
clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
}
static int snd_serial_generic_output_open(struct snd_rawmidi_substream *substream)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
int err;
dev_dbg(drvdata->card->dev, "Opening output for card %s\n",
drvdata->card->shortname);
err = snd_serial_generic_ensure_serdev_open(drvdata);
if (err < 0)
return err;
set_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode);
drvdata->midi_output = substream;
return 0;
};
static int snd_serial_generic_output_close(struct snd_rawmidi_substream *substream)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
dev_dbg(drvdata->card->dev, "Closing output for card %s\n",
drvdata->card->shortname);
clear_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode);
clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
if (!drvdata->filemode)
serdev_device_close(drvdata->serdev);
drvdata->midi_output = NULL;
return 0;
};
static void snd_serial_generic_output_trigger(struct snd_rawmidi_substream *substream,
int up)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
if (up)
set_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
else
clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
if (up)
snd_serial_generic_tx_wakeup(drvdata);
}
static void snd_serial_generic_output_drain(struct snd_rawmidi_substream *substream)
{
struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
/* Flush any pending characters */
serdev_device_write_flush(drvdata->serdev);
cancel_work_sync(&drvdata->tx_work);
}
static const struct snd_rawmidi_ops snd_serial_generic_output = {
.open = snd_serial_generic_output_open,
.close = snd_serial_generic_output_close,
.trigger = snd_serial_generic_output_trigger,
.drain = snd_serial_generic_output_drain,
};
static const struct snd_rawmidi_ops snd_serial_generic_input = {
.open = snd_serial_generic_input_open,
.close = snd_serial_generic_input_close,
.trigger = snd_serial_generic_input_trigger,
};
static void snd_serial_generic_parse_dt(struct serdev_device *serdev,
struct snd_serial_generic *drvdata)
{
int err;
err = of_property_read_u32(serdev->dev.of_node, "current-speed",
&drvdata->baudrate);
if (err < 0) {
dev_dbg(drvdata->card->dev,
"MIDI device reading of current-speed DT param failed with error %d, using default of 38400\n",
err);
drvdata->baudrate = 38400;
}
}
static void snd_serial_generic_substreams(struct snd_rawmidi_str *stream, int dev_num)
{
struct snd_rawmidi_substream *substream;
list_for_each_entry(substream, &stream->substreams, list) {
sprintf(substream->name, "Serial MIDI %d-%d", dev_num, substream->number);
}
}
static int snd_serial_generic_rmidi(struct snd_serial_generic *drvdata,
int outs, int ins, struct snd_rawmidi **rmidi)
{
struct snd_rawmidi *rrawmidi;
int err;
err = snd_rawmidi_new(drvdata->card, drvdata->card->driver, 0,
outs, ins, &rrawmidi);
if (err < 0)
return err;
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&snd_serial_generic_input);
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&snd_serial_generic_output);
strcpy(rrawmidi->name, drvdata->card->shortname);
snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
drvdata->serdev->ctrl->nr);
snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
drvdata->serdev->ctrl->nr);
rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
if (rmidi)
*rmidi = rrawmidi;
return 0;
}
static int snd_serial_generic_probe(struct serdev_device *serdev)
{
struct snd_card *card;
struct snd_serial_generic *drvdata;
int err;
err = snd_devm_card_new(&serdev->dev, SNDRV_DEFAULT_IDX1,
SNDRV_DEFAULT_STR1, THIS_MODULE,
sizeof(struct snd_serial_generic), &card);
if (err < 0)
return err;
strcpy(card->driver, "SerialMIDI");
sprintf(card->shortname, "SerialMIDI-%d", serdev->ctrl->nr);
sprintf(card->longname, "Serial MIDI device at serial%d", serdev->ctrl->nr);
drvdata = card->private_data;
drvdata->serdev = serdev;
drvdata->card = card;
snd_serial_generic_parse_dt(serdev, drvdata);
INIT_WORK(&drvdata->tx_work, snd_serial_generic_tx_work);
err = snd_serial_generic_rmidi(drvdata, 1, 1, &drvdata->rmidi);
if (err < 0)
return err;
serdev_device_set_client_ops(serdev, &snd_serial_generic_serdev_device_ops);
serdev_device_set_drvdata(drvdata->serdev, drvdata);
err = snd_card_register(card);
if (err < 0)
return err;
return 0;
}
static const struct of_device_id snd_serial_generic_dt_ids[] = {
{ .compatible = "serial-midi" },
{},
};
MODULE_DEVICE_TABLE(of, snd_serial_generic_dt_ids);
static struct serdev_device_driver snd_serial_generic_driver = {
.driver = {
.name = "snd-serial-generic",
.of_match_table = of_match_ptr(snd_serial_generic_dt_ids),
},
.probe = snd_serial_generic_probe,
};
module_serdev_device_driver(snd_serial_generic_driver);

View File

@ -129,7 +129,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
return 0;
/* the u32 cast is okay because in snd*create we successfully told
pci alloc that we're only 32 bit capable so the uppper will be 0 */
pci alloc that we're only 32 bit capable so the upper will be 0 */
addr = (u32) substream->runtime->dma_addr;
desc_addr = (u32) dma->desc_buf.addr;
for (i = 0; i < periods; i++) {

View File

@ -36,6 +36,7 @@
| ((IEC958_AES3_CON_FS_48000) << 24))
static const struct snd_pci_quirk subsys_20k1_list[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0021, "SB046x", CTSB046X),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
@ -64,6 +65,7 @@ static const struct snd_pci_quirk subsys_20k2_list[] = {
static const char *ct_subsys_name[NUM_CTCARDS] = {
/* 20k1 models */
[CTSB046X] = "SB046x",
[CTSB055X] = "SB055x",
[CTSB073X] = "SB073x",
[CTUAA] = "UAA",

View File

@ -26,8 +26,9 @@ enum CHIPTYP {
enum CTCARDS {
/* 20k1 models */
CTSB046X,
CT20K1_MODEL_FIRST = CTSB046X,
CTSB055X,
CT20K1_MODEL_FIRST = CTSB055X,
CTSB073X,
CTUAA,
CT20K1_UNKNOWN,

View File

@ -1916,7 +1916,7 @@ static int hw_card_start(struct hw *hw)
}
/* Switch to X-Fi mode from UAA mode if neeeded */
/* Switch to X-Fi mode from UAA mode if needed */
if (hw->model == CTUAA) {
err = uaa_to_xfi(pci);
if (err)

View File

@ -124,7 +124,6 @@ static int midi_service_irq(struct echoaudio *chip)
return 0;
/* Get the MIDI data from the comm page */
i = 1;
received = 0;
for (i = 1; i <= count; i++) {
/* Get the MIDI byte */

View File

@ -1751,11 +1751,8 @@ static void snd_emu10k1_detect_iommu(struct snd_emu10k1 *emu)
emu->iommu_workaround = false;
if (!iommu_present(emu->card->dev->bus))
return;
domain = iommu_get_domain_for_dev(emu->card->dev);
if (domain && domain->type == IOMMU_DOMAIN_IDENTITY)
if (!domain || domain->type == IOMMU_DOMAIN_IDENTITY)
return;
dev_notice(emu->card->dev,

View File

@ -102,6 +102,7 @@ config SND_HDA_SCODEC_CS35L41_I2C
select SND_HDA_GENERIC
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
select REGMAP_IRQ
help
Say Y or M here to include CS35L41 I2C HD-audio side codec support
in snd-hda-intel driver, such as ALC287.
@ -117,6 +118,7 @@ config SND_HDA_SCODEC_CS35L41_SPI
select SND_HDA_GENERIC
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
select REGMAP_IRQ
help
Say Y or M here to include CS35L41 SPI HD-audio side codec support
in snd-hda-intel driver, such as ALC287.

View File

@ -17,163 +17,88 @@
#include "cs35l41_hda.h"
static const struct reg_sequence cs35l41_hda_config[] = {
{ CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3200000Hz, BCLK Input, PLL_REFCLK_EN = 1
{ CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
{ CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz
{ CS35L41_SP_ENABLES, 0x00010000 }, // ASP_RX1_EN = 1
{ CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz
{ CS35L41_SP_FORMAT, 0x20200200 }, // 24 bits, I2S, BCLK Slave, FSYNC Slave
{ CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer
{ CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1
{ CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB
{ CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB
{ CS35L41_PWR_CTRL2, 0x00000001 }, // AMP_EN = 1
};
static const struct reg_sequence cs35l41_hda_start_bst[] = {
{ CS35L41_PWR_CTRL2, 0x00000021 }, // BST_EN = 10, AMP_EN = 1
{ CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
};
static const struct reg_sequence cs35l41_hda_stop_bst[] = {
{ CS35L41_PWR_CTRL1, 0x00000000, 3000}, // set GLOBAL_EN = 0
};
// only on amps where GPIO1 is used to control ext. VSPK switch
static const struct reg_sequence cs35l41_start_ext_vspk[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
{ 0x00007414, 0x08C82222 },
{ 0x0000742C, 0x00000009 },
{ 0x00011008, 0x00008001 },
{ 0x0000742C, 0x0000000F },
{ 0x0000742C, 0x00000079 },
{ 0x00007438, 0x00585941 },
{ CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1
{ 0x0000742C, 0x000000F9 },
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
//only on amps where GPIO1 is used to control ext. VSPK switch
static const struct reg_sequence cs35l41_stop_ext_vspk[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
{ 0x00002014, 0x00000000, 3000}, // set GLOBAL_EN = 0
{ 0x0000742C, 0x00000009 },
{ 0x00007438, 0x00580941 },
{ 0x00011008, 0x00000001 },
{ 0x0000393C, 0x000000C0, 6000},
{ 0x0000393C, 0x00000000 },
{ 0x00007414, 0x00C82222 },
{ 0x0000742C, 0x00000000 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
static const struct reg_sequence cs35l41_safe_to_active[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x0000742C, 0x0000000F },
{ 0x0000742C, 0x00000079 },
{ 0x00007438, 0x00585941 },
{ CS35L41_PWR_CTRL1, 0x00000001, 2000 }, // GLOBAL_EN = 1
{ 0x0000742C, 0x000000F9 },
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
static const struct reg_sequence cs35l41_active_to_safe[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
static const struct reg_sequence cs35l41_hda_mute[] = {
{ CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB
{ CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
{ CS35L41_PWR_CTRL2, 0x00000000 }, // AMP_EN = 0
{ CS35L41_PWR_CTRL1, 0x00000000 },
{ 0x0000742C, 0x00000009, 2000 },
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
static const struct reg_sequence cs35l41_reset_to_safe[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
{ 0x00007414, 0x08C82222 },
{ 0x0000742C, 0x00000009 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
/* Protection release cycle to get the speaker out of Safe-Mode */
static void cs35l41_error_release(struct device *dev, struct regmap *regmap, unsigned int mask)
{
regmap_write(regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
regmap_set_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);
regmap_clear_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);
}
static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
.probe = cs35l41_reset_to_safe,
.num_probe = ARRAY_SIZE(cs35l41_reset_to_safe),
.open = cs35l41_hda_config,
.num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_safe_to_active,
.num_prepare = ARRAY_SIZE(cs35l41_safe_to_active),
.cleanup = cs35l41_active_to_safe,
.num_cleanup = ARRAY_SIZE(cs35l41_active_to_safe),
};
static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
.open = cs35l41_hda_config,
.num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_start_ext_vspk,
.num_prepare = ARRAY_SIZE(cs35l41_start_ext_vspk),
.cleanup = cs35l41_stop_ext_vspk,
.num_cleanup = ARRAY_SIZE(cs35l41_stop_ext_vspk),
};
static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = {
.open = cs35l41_hda_config,
.num_open = ARRAY_SIZE(cs35l41_hda_config),
.prepare = cs35l41_hda_start_bst,
.num_prepare = ARRAY_SIZE(cs35l41_hda_start_bst),
.cleanup = cs35l41_hda_stop_bst,
.num_cleanup = ARRAY_SIZE(cs35l41_hda_stop_bst),
};
/* Clear all errors to release safe mode. Global Enable must be cleared first. */
static void cs35l41_irq_release(struct cs35l41_hda *cs35l41)
{
cs35l41_error_release(cs35l41->dev, cs35l41->regmap, cs35l41->irq_errors);
cs35l41->irq_errors = 0;
}
static void cs35l41_hda_playback_hook(struct device *dev, int action)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
struct regmap *reg = cs35l41->regmap;
int ret = 0;
switch (action) {
case HDA_GEN_PCM_ACT_OPEN:
if (reg_seq->open)
ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));
ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);
break;
case HDA_GEN_PCM_ACT_PREPARE:
if (reg_seq->prepare)
ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1);
break;
case HDA_GEN_PCM_ACT_CLEANUP:
if (reg_seq->cleanup)
ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0);
break;
case HDA_GEN_PCM_ACT_CLOSE:
if (reg_seq->close)
ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001);
cs35l41_irq_release(cs35l41);
break;
default:
ret = -EINVAL;
dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action);
break;
}
if (ret)
dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret);
}
static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
static const char * const channel_name[] = { "L", "R" };
if (!cs35l41->amp_name) {
if (*rx_slot >= ARRAY_SIZE(channel_name))
return -EINVAL;
cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%s%d",
channel_name[*rx_slot], cs35l41->channel_index);
if (!cs35l41->amp_name)
return -ENOMEM;
}
return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,
rx_slot);
@ -194,7 +119,6 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
comps->dev = dev;
strscpy(comps->name, dev_name(dev), sizeof(comps->name));
comps->playback_hook = cs35l41_hda_playback_hook;
comps->set_channel_map = cs35l41_hda_channel_map;
return 0;
}
@ -213,67 +137,169 @@ static const struct component_ops cs35l41_hda_comp_ops = {
.unbind = cs35l41_hda_unbind,
};
static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
const struct cs35l41_hda_hw_config *hw_cfg)
static irqreturn_t cs35l41_bst_short_err(int irq, void *data)
{
bool internal_boost = false;
int ret;
struct cs35l41_hda *cs35l41 = data;
if (!hw_cfg) {
cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
return 0;
}
dev_crit_ratelimited(cs35l41->dev, "LBST Error\n");
set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);
if (hw_cfg->bst_ind || hw_cfg->bst_cap || hw_cfg->bst_ipk)
internal_boost = true;
switch (hw_cfg->gpio1_func) {
case CS35L41_NOT_USED:
break;
case CS35l41_VSPK_SWITCH:
regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
break;
case CS35l41_SYNC:
regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
break;
default:
dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n", hw_cfg->gpio1_func);
return -EINVAL;
}
switch (hw_cfg->gpio2_func) {
case CS35L41_NOT_USED:
break;
case CS35L41_INTERRUPT:
regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT);
break;
default:
dev_err(cs35l41->dev, "Invalid function %d for GPIO2\n", hw_cfg->gpio2_func);
return -EINVAL;
}
if (internal_boost) {
cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst;
if (!(hw_cfg->bst_ind && hw_cfg->bst_cap && hw_cfg->bst_ipk))
return -EINVAL;
ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
if (ret)
return ret;
} else {
cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
}
return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
return IRQ_HANDLED;
}
static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41,
const char *hid, int id)
static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data)
{
struct cs35l41_hda_hw_config *hw_cfg;
struct cs35l41_hda *cs35l41 = data;
dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");
set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
return IRQ_HANDLED;
}
static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data)
{
struct cs35l41_hda *cs35l41 = data;
dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");
set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
return IRQ_HANDLED;
}
static irqreturn_t cs35l41_temp_err(int irq, void *data)
{
struct cs35l41_hda *cs35l41 = data;
dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");
set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
return IRQ_HANDLED;
}
static irqreturn_t cs35l41_temp_warn(int irq, void *data)
{
struct cs35l41_hda *cs35l41 = data;
dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");
set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors);
return IRQ_HANDLED;
}
static irqreturn_t cs35l41_amp_short(int irq, void *data)
{
struct cs35l41_hda *cs35l41 = data;
dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");
set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);
return IRQ_HANDLED;
}
static const struct cs35l41_irq cs35l41_irqs[] = {
CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err),
CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err),
CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err),
CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn),
CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err),
CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short),
};
static const struct regmap_irq cs35l41_reg_irqs[] = {
CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR),
CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR),
CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR),
CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN),
CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR),
CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),
};
static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {
.name = "cs35l41 IRQ1 Controller",
.status_base = CS35L41_IRQ1_STATUS1,
.mask_base = CS35L41_IRQ1_MASK1,
.ack_base = CS35L41_IRQ1_STATUS1,
.num_regs = 4,
.irqs = cs35l41_reg_irqs,
.num_irqs = ARRAY_SIZE(cs35l41_reg_irqs),
};
static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
{
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
bool using_irq = false;
int irq, irq_pol;
int ret;
int i;
if (!cs35l41->hw_cfg.valid)
return -EINVAL;
ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
if (ret)
return ret;
if (hw_cfg->gpio1.valid) {
switch (hw_cfg->gpio1.func) {
case CS35L41_NOT_USED:
break;
case CS35l41_VSPK_SWITCH:
hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO;
hw_cfg->gpio1.out_en = true;
break;
case CS35l41_SYNC:
hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC;
break;
default:
dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",
hw_cfg->gpio1.func);
return -EINVAL;
}
}
if (hw_cfg->gpio2.valid) {
switch (hw_cfg->gpio2.func) {
case CS35L41_NOT_USED:
break;
case CS35L41_INTERRUPT:
using_irq = true;
break;
default:
dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);
return -EINVAL;
}
}
irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);
if (cs35l41->irq && using_irq) {
ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {
irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);
if (irq < 0)
return irq;
ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,
cs35l41_irqs[i].handler,
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
cs35l41_irqs[i].name, cs35l41);
if (ret)
return ret;
}
}
return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
}
static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)
{
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
u32 values[HDA_MAX_COMPONENTS];
struct acpi_device *adev;
struct device *physdev;
@ -284,7 +310,7 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
if (!adev) {
dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
return ERR_PTR(-ENODEV);
return -ENODEV;
}
physdev = get_device(acpi_get_first_physical_node(adev));
@ -324,56 +350,67 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
GPIOD_OUT_LOW, "cs35l41-reset");
hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
if (!hw_cfg) {
ret = -ENOMEM;
goto err;
}
property = "cirrus,speaker-position";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
goto err_free;
goto err;
hw_cfg->spk_pos = values[cs35l41->index];
cs35l41->channel_index = 0;
for (i = 0; i < cs35l41->index; i++)
if (values[i] == hw_cfg->spk_pos)
cs35l41->channel_index++;
property = "cirrus,gpio1-func";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
goto err_free;
hw_cfg->gpio1_func = values[cs35l41->index];
goto err;
hw_cfg->gpio1.func = values[cs35l41->index];
hw_cfg->gpio1.valid = true;
property = "cirrus,gpio2-func";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
goto err_free;
hw_cfg->gpio2_func = values[cs35l41->index];
goto err;
hw_cfg->gpio2.func = values[cs35l41->index];
hw_cfg->gpio2.valid = true;
property = "cirrus,boost-peak-milliamp";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret == 0)
hw_cfg->bst_ipk = values[cs35l41->index];
else
hw_cfg->bst_ipk = -1;
property = "cirrus,boost-ind-nanohenry";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret == 0)
hw_cfg->bst_ind = values[cs35l41->index];
else
hw_cfg->bst_ind = -1;
property = "cirrus,boost-cap-microfarad";
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret == 0)
hw_cfg->bst_cap = values[cs35l41->index];
else
hw_cfg->bst_cap = -1;
if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)
hw_cfg->bst_type = CS35L41_INT_BOOST;
else
hw_cfg->bst_type = CS35L41_EXT_BOOST;
hw_cfg->valid = true;
put_device(physdev);
return hw_cfg;
return 0;
err_free:
kfree(hw_cfg);
err:
put_device(physdev);
dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);
return ERR_PTR(ret);
return ret;
no_acpi_dsd:
/*
@ -384,25 +421,32 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c
* fwnode.
*/
if (strncmp(hid, "CLSA0100", 8) != 0)
return ERR_PTR(-EINVAL);
return -EINVAL;
/* check I2C address to assign the index */
cs35l41->index = id == 0x40 ? 0 : 1;
cs35l41->hw_cfg.spk_pos = cs35l41->index;
cs35l41->channel_index = 0;
cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
cs35l41->vspk_always_on = true;
cs35l41->hw_cfg.bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH;
hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;
hw_cfg->gpio2.valid = true;
cs35l41->hw_cfg.valid = true;
put_device(physdev);
return NULL;
return 0;
}
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
struct regmap *regmap)
{
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
struct cs35l41_hda_hw_config *acpi_hw_cfg;
struct cs35l41_hda *cs35l41;
int ret;
BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs));
BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@ -415,9 +459,11 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
cs35l41->regmap = regmap;
dev_set_drvdata(dev, cs35l41);
acpi_hw_cfg = cs35l41_hda_read_acpi(cs35l41, device_name, id);
if (IS_ERR(acpi_hw_cfg))
return PTR_ERR(acpi_hw_cfg);
ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
if (ret) {
dev_err_probe(cs35l41->dev, ret, "Platform not supported %d\n", ret);
return ret;
}
if (IS_ERR(cs35l41->reset_gpio)) {
ret = PTR_ERR(cs35l41->reset_gpio);
@ -490,20 +536,9 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (ret)
goto err;
ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
ret = cs35l41_hda_apply_properties(cs35l41);
if (ret)
goto err;
kfree(acpi_hw_cfg);
acpi_hw_cfg = NULL;
if (cs35l41->reg_seq->probe) {
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41->reg_seq->probe,
cs35l41->reg_seq->num_probe);
if (ret) {
dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
goto err;
}
}
ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
if (ret) {
@ -516,8 +551,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0;
err:
kfree(acpi_hw_cfg);
if (!cs35l41->vspk_always_on)
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
@ -531,7 +565,7 @@ void cs35l41_hda_remove(struct device *dev)
component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
if (!cs35l41->vspk_always_on)
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
}

View File

@ -27,39 +27,18 @@ enum cs35l41_hda_gpio_function {
CS35l41_SYNC,
};
struct cs35l41_hda_reg_sequence {
const struct reg_sequence *probe;
unsigned int num_probe;
const struct reg_sequence *open;
unsigned int num_open;
const struct reg_sequence *prepare;
unsigned int num_prepare;
const struct reg_sequence *cleanup;
unsigned int num_cleanup;
const struct reg_sequence *close;
unsigned int num_close;
};
struct cs35l41_hda_hw_config {
unsigned int spk_pos;
unsigned int gpio1_func;
unsigned int gpio2_func;
int bst_ind;
int bst_ipk;
int bst_cap;
};
struct cs35l41_hda {
struct device *dev;
struct regmap *regmap;
struct gpio_desc *reset_gpio;
const struct cs35l41_hda_reg_sequence *reg_seq;
struct cs35l41_hw_cfg hw_cfg;
int irq;
int index;
/* Don't put the AMP in reset of VSPK can not be turned off */
bool vspk_always_on;
int channel_index;
unsigned volatile long irq_errors;
const char *amp_name;
struct regmap_irq_chip_data *irq_data;
};
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,

View File

@ -48,7 +48,7 @@ MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
static struct spi_driver cs35l41_spi_driver = {
.driver = {
.name = "cs35l41_hda",
.name = "cs35l41-hda",
.acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
},
.id_table = cs35l41_hda_spi_id,

View File

@ -2935,7 +2935,9 @@ static int hda_codec_runtime_suspend(struct device *dev)
if (!codec->card)
return 0;
cancel_delayed_work_sync(&codec->jackpoll_work);
if (!codec->bus->jackpoll_in_suspend)
cancel_delayed_work_sync(&codec->jackpoll_work);
state = hda_call_codec_suspend(codec);
if (codec->link_down_at_suspend ||
(codec_has_clkstop(codec) && codec_has_epss(codec) &&
@ -2984,6 +2986,9 @@ static void hda_codec_pm_complete(struct device *dev)
static int hda_codec_pm_suspend(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
cancel_delayed_work_sync(&codec->jackpoll_work);
dev->power.power_state = PMSG_SUSPEND;
return pm_runtime_force_suspend(dev);
}
@ -2996,6 +3001,9 @@ static int hda_codec_pm_resume(struct device *dev)
static int hda_codec_pm_freeze(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
cancel_delayed_work_sync(&codec->jackpoll_work);
dev->power.power_state = PMSG_FREEZE;
return pm_runtime_force_suspend(dev);
}
@ -3038,6 +3046,7 @@ void snd_hda_codec_shutdown(struct hda_codec *codec)
if (!codec->registered)
return;
cancel_delayed_work_sync(&codec->jackpoll_work);
list_for_each_entry(cpcm, &codec->pcm_list_head, list)
snd_pcm_suspend_all(cpcm->pcm);

View File

@ -15,6 +15,4 @@ struct hda_component {
struct device *dev;
char name[HDA_MAX_NAME_SIZE];
void (*playback_hook)(struct device *dev, int action);
int (*set_channel_map)(struct device *dev, unsigned int rx_num, unsigned int *rx_slot,
unsigned int tx_num, unsigned int *tx_slot);
};

View File

@ -420,6 +420,7 @@ static int hda_tegra_create(struct snd_card *card,
chip->driver_caps = driver_caps;
chip->driver_type = driver_caps & 0xff;
chip->dev_index = 0;
chip->jackpoll_interval = msecs_to_jiffies(5000);
INIT_LIST_HEAD(&chip->pcm_list);
chip->codec_probe_mask = -1;
@ -436,6 +437,7 @@ static int hda_tegra_create(struct snd_card *card,
chip->bus.core.sync_write = 0;
chip->bus.core.needs_damn_long_delay = 1;
chip->bus.core.aligned_mmio = 1;
chip->bus.jackpoll_in_suspend = 1;
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {

View File

@ -1105,6 +1105,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
static const struct hda_device_id snd_hda_id_conexant[] = {
HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f11f87, "SN6140", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),

View File

@ -76,67 +76,74 @@ const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
{} /* terminator */
};
const struct hda_pintbl cs8409_cs42l42_pincfgs_no_dmic[] = {
{ CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
{ CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
{ CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
{} /* terminator */
};
/* Vendor specific HW configuration for CS42L42 */
static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
{ 0x1010, 0xB0 },
{ 0x1D01, 0x00 },
{ CS42L42_I2C_TIMEOUT, 0xB0 },
{ CS42L42_ADC_CTL, 0x00 },
{ 0x1D02, 0x06 },
{ 0x1D03, 0x9F },
{ 0x1107, 0x01 },
{ 0x1009, 0x02 },
{ 0x1007, 0x03 },
{ 0x1201, 0x00 },
{ 0x1208, 0x13 },
{ 0x1205, 0xFF },
{ 0x1206, 0x00 },
{ 0x1207, 0x20 },
{ 0x1202, 0x0D },
{ 0x2A02, 0x02 },
{ 0x2A03, 0x00 },
{ 0x2A04, 0x00 },
{ 0x2A05, 0x02 },
{ 0x2A06, 0x00 },
{ 0x2A07, 0x20 },
{ 0x2A08, 0x02 },
{ 0x2A09, 0x00 },
{ 0x2A0A, 0x80 },
{ 0x2A0B, 0x02 },
{ 0x2A0C, 0x00 },
{ 0x2A0D, 0xA0 },
{ 0x2A01, 0x0C },
{ 0x2902, 0x01 },
{ 0x2903, 0x02 },
{ 0x2904, 0x00 },
{ 0x2905, 0x00 },
{ 0x2901, 0x01 },
{ 0x1101, 0x0A },
{ 0x1102, 0x84 },
{ 0x2301, 0x3F },
{ 0x2303, 0x3F },
{ 0x2302, 0x3f },
{ 0x2001, 0x03 },
{ 0x1B75, 0xB6 },
{ 0x1B73, 0xC2 },
{ 0x1129, 0x01 },
{ 0x1121, 0xF3 },
{ 0x1103, 0x20 },
{ 0x1105, 0x00 },
{ 0x1112, 0x00 },
{ 0x1113, 0x80 },
{ 0x1C03, 0xC0 },
{ 0x1101, 0x02 },
{ 0x1316, 0xff },
{ 0x1317, 0xff },
{ 0x1318, 0xff },
{ 0x1319, 0xff },
{ 0x131a, 0xff },
{ 0x131b, 0xff },
{ 0x131c, 0xff },
{ 0x131e, 0xff },
{ 0x131f, 0xff },
{ 0x1320, 0xff },
{ 0x1b79, 0xff },
{ 0x1b7a, 0xff },
{ CS42L42_ADC_VOLUME, 0x9F },
{ CS42L42_OSC_SWITCH, 0x01 },
{ CS42L42_MCLK_CTL, 0x02 },
{ CS42L42_SRC_CTL, 0x03 },
{ CS42L42_MCLK_SRC_SEL, 0x00 },
{ CS42L42_ASP_FRM_CFG, 0x13 },
{ CS42L42_FSYNC_P_LOWER, 0xFF },
{ CS42L42_FSYNC_P_UPPER, 0x00 },
{ CS42L42_ASP_CLK_CFG, 0x20 },
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
{ CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x80 },
{ CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0xA0 },
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
{ CS42L42_ASP_TX_CH_EN, 0x01 },
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
{ CS42L42_ASP_TX_SZ_EN, 0x01 },
{ CS42L42_PWR_CTL1, 0x0A },
{ CS42L42_PWR_CTL2, 0x84 },
{ CS42L42_MIXER_CHA_VOL, 0x3F },
{ CS42L42_MIXER_CHB_VOL, 0x3F },
{ CS42L42_MIXER_ADC_VOL, 0x3f },
{ CS42L42_HP_CTL, 0x03 },
{ CS42L42_MIC_DET_CTL1, 0xB6 },
{ CS42L42_TIPSENSE_CTL, 0xC2 },
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
{ CS42L42_PWR_CTL3, 0x20 },
{ CS42L42_RSENSE_CTL2, 0x00 },
{ CS42L42_RSENSE_CTL3, 0x00 },
{ CS42L42_TSENSE_CTL, 0x80 },
{ CS42L42_HS_BIAS_CTL, 0xC0 },
{ CS42L42_PWR_CTL1, 0x02 },
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
{ CS42L42_MIXER_INT_MASK, 0xff },
{ CS42L42_SRC_INT_MASK, 0xff },
{ CS42L42_ASP_RX_INT_MASK, 0xff },
{ CS42L42_ASP_TX_INT_MASK, 0xff },
{ CS42L42_CODEC_INT_MASK, 0xff },
{ CS42L42_SRCPL_INT_MASK, 0xff },
{ CS42L42_VPMON_INT_MASK, 0xff },
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
{ CS42L42_DET_INT1_MASK, 0xff },
{ CS42L42_DET_INT2_MASK, 0xff },
};
/* Vendor specific hw configuration for CS8409 */
@ -252,7 +259,6 @@ struct sub_codec cs8409_cs42l42_codec = {
.init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
.hp_jack_in = 0,
.mic_jack_in = 0,
.force_status_change = 1,
.paged = 1,
.suspended = 1,
.no_type_dect = 0,
@ -282,115 +288,115 @@ const struct hda_pintbl dolphin_pincfgs[] = {
/* Vendor specific HW configuration for CS42L42 */
static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
{ 0x1010, 0xB0 },
{ 0x1D01, 0x00 },
{ CS42L42_I2C_TIMEOUT, 0xB0 },
{ CS42L42_ADC_CTL, 0x00 },
{ 0x1D02, 0x06 },
{ 0x1D03, 0x9F },
{ 0x1107, 0x01 },
{ 0x1009, 0x02 },
{ 0x1007, 0x03 },
{ 0x1201, 0x00 },
{ 0x1208, 0x13 },
{ 0x1205, 0xFF },
{ 0x1206, 0x00 },
{ 0x1207, 0x20 },
{ 0x1202, 0x0D },
{ 0x2A02, 0x02 },
{ 0x2A03, 0x00 },
{ 0x2A04, 0x00 },
{ 0x2A05, 0x02 },
{ 0x2A06, 0x00 },
{ 0x2A07, 0x20 },
{ 0x2A01, 0x0C },
{ 0x2902, 0x01 },
{ 0x2903, 0x02 },
{ 0x2904, 0x00 },
{ 0x2905, 0x00 },
{ 0x2901, 0x01 },
{ 0x1101, 0x0A },
{ 0x1102, 0x84 },
{ 0x2001, 0x03 },
{ 0x2301, 0x3F },
{ 0x2303, 0x3F },
{ 0x2302, 0x3f },
{ 0x1B75, 0xB6 },
{ 0x1B73, 0xC2 },
{ 0x1129, 0x01 },
{ 0x1121, 0xF3 },
{ 0x1103, 0x20 },
{ 0x1105, 0x00 },
{ 0x1112, 0x00 },
{ 0x1113, 0x80 },
{ 0x1C03, 0xC0 },
{ 0x1101, 0x02 },
{ 0x1316, 0xff },
{ 0x1317, 0xff },
{ 0x1318, 0xff },
{ 0x1319, 0xff },
{ 0x131a, 0xff },
{ 0x131b, 0xff },
{ 0x131c, 0xff },
{ 0x131e, 0xff },
{ 0x131f, 0xff },
{ 0x1320, 0xff },
{ 0x1b79, 0xff },
{ 0x1b7a, 0xff }
{ CS42L42_ADC_VOLUME, 0x9F },
{ CS42L42_OSC_SWITCH, 0x01 },
{ CS42L42_MCLK_CTL, 0x02 },
{ CS42L42_SRC_CTL, 0x03 },
{ CS42L42_MCLK_SRC_SEL, 0x00 },
{ CS42L42_ASP_FRM_CFG, 0x13 },
{ CS42L42_FSYNC_P_LOWER, 0xFF },
{ CS42L42_FSYNC_P_UPPER, 0x00 },
{ CS42L42_ASP_CLK_CFG, 0x20 },
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
{ CS42L42_ASP_TX_CH_EN, 0x01 },
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
{ CS42L42_ASP_TX_SZ_EN, 0x01 },
{ CS42L42_PWR_CTL1, 0x0A },
{ CS42L42_PWR_CTL2, 0x84 },
{ CS42L42_HP_CTL, 0x03 },
{ CS42L42_MIXER_CHA_VOL, 0x3F },
{ CS42L42_MIXER_CHB_VOL, 0x3F },
{ CS42L42_MIXER_ADC_VOL, 0x3f },
{ CS42L42_MIC_DET_CTL1, 0xB6 },
{ CS42L42_TIPSENSE_CTL, 0xC2 },
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
{ CS42L42_PWR_CTL3, 0x20 },
{ CS42L42_RSENSE_CTL2, 0x00 },
{ CS42L42_RSENSE_CTL3, 0x00 },
{ CS42L42_TSENSE_CTL, 0x80 },
{ CS42L42_HS_BIAS_CTL, 0xC0 },
{ CS42L42_PWR_CTL1, 0x02 },
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
{ CS42L42_MIXER_INT_MASK, 0xff },
{ CS42L42_SRC_INT_MASK, 0xff },
{ CS42L42_ASP_RX_INT_MASK, 0xff },
{ CS42L42_ASP_TX_INT_MASK, 0xff },
{ CS42L42_CODEC_INT_MASK, 0xff },
{ CS42L42_SRCPL_INT_MASK, 0xff },
{ CS42L42_VPMON_INT_MASK, 0xff },
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
{ CS42L42_DET_INT1_MASK, 0xff },
{ CS42L42_DET_INT2_MASK, 0xff }
};
static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
{ 0x1010, 0xB0 },
{ 0x1D01, 0x00 },
{ CS42L42_I2C_TIMEOUT, 0xB0 },
{ CS42L42_ADC_CTL, 0x00 },
{ 0x1D02, 0x06 },
{ 0x1D03, 0x9F },
{ 0x1107, 0x01 },
{ 0x1009, 0x02 },
{ 0x1007, 0x03 },
{ 0x1201, 0x00 },
{ 0x1208, 0x13 },
{ 0x1205, 0xFF },
{ 0x1206, 0x00 },
{ 0x1207, 0x20 },
{ 0x1202, 0x0D },
{ 0x2A02, 0x02 },
{ 0x2A03, 0x00 },
{ 0x2A04, 0x80 },
{ 0x2A05, 0x02 },
{ 0x2A06, 0x00 },
{ 0x2A07, 0xA0 },
{ 0x2A01, 0x0C },
{ 0x2902, 0x00 },
{ 0x2903, 0x02 },
{ 0x2904, 0x00 },
{ 0x2905, 0x00 },
{ 0x2901, 0x00 },
{ 0x1101, 0x0E },
{ 0x1102, 0x84 },
{ 0x2001, 0x01 },
{ 0x2301, 0x3F },
{ 0x2303, 0x3F },
{ 0x2302, 0x3f },
{ 0x1B75, 0xB6 },
{ 0x1B73, 0xC2 },
{ 0x1129, 0x01 },
{ 0x1121, 0xF3 },
{ 0x1103, 0x20 },
{ 0x1105, 0x00 },
{ 0x1112, 0x00 },
{ 0x1113, 0x80 },
{ 0x1C03, 0xC0 },
{ 0x1101, 0x06 },
{ 0x1316, 0xff },
{ 0x1317, 0xff },
{ 0x1318, 0xff },
{ 0x1319, 0xff },
{ 0x131a, 0xff },
{ 0x131b, 0xff },
{ 0x131c, 0xff },
{ 0x131e, 0xff },
{ 0x131f, 0xff },
{ 0x1320, 0xff },
{ 0x1b79, 0xff },
{ 0x1b7a, 0xff }
{ CS42L42_ADC_VOLUME, 0x9F },
{ CS42L42_OSC_SWITCH, 0x01 },
{ CS42L42_MCLK_CTL, 0x02 },
{ CS42L42_SRC_CTL, 0x03 },
{ CS42L42_MCLK_SRC_SEL, 0x00 },
{ CS42L42_ASP_FRM_CFG, 0x13 },
{ CS42L42_FSYNC_P_LOWER, 0xFF },
{ CS42L42_FSYNC_P_UPPER, 0x00 },
{ CS42L42_ASP_CLK_CFG, 0x20 },
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x80 },
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0xA0 },
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
{ CS42L42_ASP_TX_CH_EN, 0x00 },
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
{ CS42L42_ASP_TX_SZ_EN, 0x00 },
{ CS42L42_PWR_CTL1, 0x0E },
{ CS42L42_PWR_CTL2, 0x84 },
{ CS42L42_HP_CTL, 0x01 },
{ CS42L42_MIXER_CHA_VOL, 0x3F },
{ CS42L42_MIXER_CHB_VOL, 0x3F },
{ CS42L42_MIXER_ADC_VOL, 0x3f },
{ CS42L42_MIC_DET_CTL1, 0xB6 },
{ CS42L42_TIPSENSE_CTL, 0xC2 },
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
{ CS42L42_PWR_CTL3, 0x20 },
{ CS42L42_RSENSE_CTL2, 0x00 },
{ CS42L42_RSENSE_CTL3, 0x00 },
{ CS42L42_TSENSE_CTL, 0x80 },
{ CS42L42_HS_BIAS_CTL, 0xC0 },
{ CS42L42_PWR_CTL1, 0x06 },
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
{ CS42L42_MIXER_INT_MASK, 0xff },
{ CS42L42_SRC_INT_MASK, 0xff },
{ CS42L42_ASP_RX_INT_MASK, 0xff },
{ CS42L42_ASP_TX_INT_MASK, 0xff },
{ CS42L42_CODEC_INT_MASK, 0xff },
{ CS42L42_SRCPL_INT_MASK, 0xff },
{ CS42L42_VPMON_INT_MASK, 0xff },
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
{ CS42L42_DET_INT1_MASK, 0xff },
{ CS42L42_DET_INT2_MASK, 0xff }
};
/* Vendor specific hw configuration for CS8409 */
@ -444,7 +450,6 @@ struct sub_codec dolphin_cs42l42_0 = {
.init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
.hp_jack_in = 0,
.mic_jack_in = 0,
.force_status_change = 1,
.paged = 1,
.suspended = 1,
.no_type_dect = 0,
@ -458,7 +463,6 @@ struct sub_codec dolphin_cs42l42_1 = {
.init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
.hp_jack_in = 0,
.mic_jack_in = 0,
.force_status_change = 1,
.paged = 1,
.suspended = 1,
.no_type_dect = 1,
@ -521,6 +525,11 @@ const struct snd_pci_quirk cs8409_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0B95, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
SND_PCI_QUIRK(0x1028, 0x0B96, "Warlock MLK", CS8409_WARLOCK_MLK),
SND_PCI_QUIRK(0x1028, 0x0B97, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
SND_PCI_QUIRK(0x1028, 0x0BA5, "Odin", CS8409_ODIN),
SND_PCI_QUIRK(0x1028, 0x0BA6, "Odin", CS8409_ODIN),
SND_PCI_QUIRK(0x1028, 0x0BA8, "Odin", CS8409_ODIN),
SND_PCI_QUIRK(0x1028, 0x0BAA, "Odin", CS8409_ODIN),
SND_PCI_QUIRK(0x1028, 0x0BAE, "Odin", CS8409_ODIN),
SND_PCI_QUIRK(0x1028, 0x0BB2, "Warlock MLK", CS8409_WARLOCK_MLK),
SND_PCI_QUIRK(0x1028, 0x0BB3, "Warlock MLK", CS8409_WARLOCK_MLK),
SND_PCI_QUIRK(0x1028, 0x0BB4, "Warlock MLK", CS8409_WARLOCK_MLK),
@ -548,6 +557,7 @@ const struct hda_model_fixup cs8409_models[] = {
{ .id = CS8409_WARLOCK_MLK_DUAL_MIC, .name = "warlock mlk dual mic" },
{ .id = CS8409_CYBORG, .name = "cyborg" },
{ .id = CS8409_DOLPHIN, .name = "dolphin" },
{ .id = CS8409_ODIN, .name = "odin" },
{}
};
@ -596,4 +606,10 @@ const struct hda_fixup cs8409_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = dolphin_fixups,
},
[CS8409_ODIN] = {
.type = HDA_FIXUP_PINS,
.v.pins = cs8409_cs42l42_pincfgs_no_dmic,
.chained = true,
.chain_id = CS8409_FIXUPS,
},
};

View File

@ -419,6 +419,39 @@ static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP));
}
static int cs8409_spk_sw_gpio_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs8409_spec *spec = codec->spec;
ucontrol->value.integer.value[0] = !!(spec->gpio_data & spec->speaker_pdn_gpio);
return 0;
}
static int cs8409_spk_sw_gpio_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs8409_spec *spec = codec->spec;
unsigned int gpio_data;
gpio_data = (spec->gpio_data & ~spec->speaker_pdn_gpio) |
(ucontrol->value.integer.value[0] ? spec->speaker_pdn_gpio : 0);
if (gpio_data == spec->gpio_data)
return 0;
spec->gpio_data = gpio_data;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
return 1;
}
static const struct snd_kcontrol_new cs8409_spk_sw_ctrl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ctl_boolean_mono_info,
.get = cs8409_spk_sw_gpio_get,
.put = cs8409_spk_sw_gpio_put,
};
/******************************************************************************
* CS42L42 Specific Functions
******************************************************************************/
@ -481,26 +514,26 @@ static void cs42l42_mute(struct sub_codec *cs42l42, int vol_type,
if (mute) {
if (vol_type == CS42L42_VOL_DAC) {
if (chs & BIT(0))
cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA, 0x3f);
cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL, 0x3f);
if (chs & BIT(1))
cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB, 0x3f);
cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL, 0x3f);
} else if (vol_type == CS42L42_VOL_ADC) {
if (chs & BIT(0))
cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL, 0x9f);
cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME, 0x9f);
}
} else {
if (vol_type == CS42L42_VOL_DAC) {
if (chs & BIT(0))
cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA,
cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL,
-(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
& CS42L42_REG_HS_VOL_MASK);
& CS42L42_MIXER_CH_VOL_MASK);
if (chs & BIT(1))
cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB,
cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL,
-(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
& CS42L42_REG_HS_VOL_MASK);
& CS42L42_MIXER_CH_VOL_MASK);
} else if (vol_type == CS42L42_VOL_ADC) {
if (chs & BIT(0))
cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL,
cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME,
cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
& CS42L42_REG_AMIC_VOL_MASK);
}
@ -601,76 +634,167 @@ static void cs42l42_capture_pcm_hook(struct hda_pcm_stream *hinfo,
/* Configure CS42L42 slave codec for jack autodetect */
static void cs42l42_enable_jack_detect(struct sub_codec *cs42l42)
{
cs8409_i2c_write(cs42l42, 0x1b70, cs42l42->hsbias_hiz);
cs8409_i2c_write(cs42l42, CS42L42_HSBIAS_SC_AUTOCTL, cs42l42->hsbias_hiz);
/* Clear WAKE# */
cs8409_i2c_write(cs42l42, 0x1b71, 0x00C1);
cs8409_i2c_write(cs42l42, CS42L42_WAKE_CTL, 0x00C1);
/* Wait ~2.5ms */
usleep_range(2500, 3000);
/* Set mode WAKE# output follows the combination logic directly */
cs8409_i2c_write(cs42l42, 0x1b71, 0x00C0);
cs8409_i2c_write(cs42l42, CS42L42_WAKE_CTL, 0x00C0);
/* Clear interrupts status */
cs8409_i2c_read(cs42l42, 0x130f);
cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
/* Enable interrupt */
cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xF3);
}
/* Enable and run CS42L42 slave codec jack auto detect */
static void cs42l42_run_jack_detect(struct sub_codec *cs42l42)
{
/* Clear interrupts */
cs8409_i2c_read(cs42l42, 0x1308);
cs8409_i2c_read(cs42l42, 0x1b77);
cs8409_i2c_write(cs42l42, 0x1320, 0xFF);
cs8409_i2c_read(cs42l42, 0x130f);
cs8409_i2c_read(cs42l42, CS42L42_CODEC_STATUS);
cs8409_i2c_read(cs42l42, CS42L42_DET_STATUS1);
cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xFF);
cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
cs8409_i2c_write(cs42l42, 0x1102, 0x87);
cs8409_i2c_write(cs42l42, 0x1f06, 0x86);
cs8409_i2c_write(cs42l42, 0x1b74, 0x07);
cs8409_i2c_write(cs42l42, 0x131b, 0xFD);
cs8409_i2c_write(cs42l42, 0x1120, 0x80);
cs8409_i2c_write(cs42l42, CS42L42_PWR_CTL2, 0x87);
cs8409_i2c_write(cs42l42, CS42L42_DAC_CTL2, 0x86);
cs8409_i2c_write(cs42l42, CS42L42_MISC_DET_CTL, 0x07);
cs8409_i2c_write(cs42l42, CS42L42_CODEC_INT_MASK, 0xFD);
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0x80);
/* Wait ~20ms*/
usleep_range(20000, 25000);
cs8409_i2c_write(cs42l42, 0x111f, 0x77);
cs8409_i2c_write(cs42l42, 0x1120, 0xc0);
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1, 0x77);
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0xc0);
}
static int cs42l42_manual_hs_det(struct sub_codec *cs42l42)
{
unsigned int hs_det_status;
unsigned int hs_det_comp1;
unsigned int hs_det_comp2;
unsigned int hs_det_sw;
unsigned int hs_type;
/* Set hs detect to manual, active mode */
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2,
(1 << CS42L42_HSDET_CTRL_SHIFT) |
(0 << CS42L42_HSDET_SET_SHIFT) |
(0 << CS42L42_HSBIAS_REF_SHIFT) |
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
/* Configure HS DET comparator reference levels. */
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1,
(CS42L42_HSDET_COMP1_LVL_VAL << CS42L42_HSDET_COMP1_LVL_SHIFT) |
(CS42L42_HSDET_COMP2_LVL_VAL << CS42L42_HSDET_COMP2_LVL_SHIFT));
/* Open the SW_HSB_HS3 switch and close SW_HSB_HS4 for a Type 1 headset. */
cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP1);
msleep(100);
hs_det_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
hs_det_comp1 = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
CS42L42_HSDET_COMP1_OUT_SHIFT;
hs_det_comp2 = (hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
CS42L42_HSDET_COMP2_OUT_SHIFT;
/* Close the SW_HSB_HS3 switch for a Type 2 headset. */
cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP2);
msleep(100);
hs_det_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
hs_det_comp1 |= ((hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
CS42L42_HSDET_COMP1_OUT_SHIFT) << 1;
hs_det_comp2 |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
/* Use Comparator 1 with 1.25V Threshold. */
switch (hs_det_comp1) {
case CS42L42_HSDET_COMP_TYPE1:
hs_type = CS42L42_PLUG_CTIA;
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
break;
case CS42L42_HSDET_COMP_TYPE2:
hs_type = CS42L42_PLUG_OMTP;
hs_det_sw = CS42L42_HSDET_SW_TYPE2;
break;
default:
/* Fallback to Comparator 2 with 1.75V Threshold. */
switch (hs_det_comp2) {
case CS42L42_HSDET_COMP_TYPE1:
hs_type = CS42L42_PLUG_CTIA;
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
break;
case CS42L42_HSDET_COMP_TYPE2:
hs_type = CS42L42_PLUG_OMTP;
hs_det_sw = CS42L42_HSDET_SW_TYPE2;
break;
case CS42L42_HSDET_COMP_TYPE3:
hs_type = CS42L42_PLUG_HEADPHONE;
hs_det_sw = CS42L42_HSDET_SW_TYPE3;
break;
default:
hs_type = CS42L42_PLUG_INVALID;
hs_det_sw = CS42L42_HSDET_SW_TYPE4;
break;
}
}
/* Set Switches */
cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, hs_det_sw);
/* Set HSDET mode to Manual—Disabled */
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2,
(0 << CS42L42_HSDET_CTRL_SHIFT) |
(0 << CS42L42_HSDET_SET_SHIFT) |
(0 << CS42L42_HSBIAS_REF_SHIFT) |
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
/* Configure HS DET comparator reference levels. */
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1,
(CS42L42_HSDET_COMP1_LVL_DEFAULT << CS42L42_HSDET_COMP1_LVL_SHIFT) |
(CS42L42_HSDET_COMP2_LVL_DEFAULT << CS42L42_HSDET_COMP2_LVL_SHIFT));
return hs_type;
}
static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status)
{
int status_changed = cs42l42->force_status_change;
cs42l42->force_status_change = 0;
int status_changed = 0;
/* TIP_SENSE INSERT/REMOVE */
switch (reg_ts_status) {
case CS42L42_JACK_INSERTED:
if (!cs42l42->hp_jack_in) {
if (cs42l42->no_type_dect) {
status_changed = 1;
cs42l42->hp_jack_in = 1;
cs42l42->mic_jack_in = 0;
} else {
cs42l42_run_jack_detect(cs42l42);
}
case CS42L42_TS_PLUG:
if (cs42l42->no_type_dect) {
status_changed = 1;
cs42l42->hp_jack_in = 1;
cs42l42->mic_jack_in = 0;
} else {
cs42l42_run_jack_detect(cs42l42);
}
break;
case CS42L42_JACK_REMOVED:
if (cs42l42->hp_jack_in || cs42l42->mic_jack_in) {
status_changed = 1;
cs42l42->hp_jack_in = 0;
cs42l42->mic_jack_in = 0;
}
case CS42L42_TS_UNPLUG:
status_changed = 1;
cs42l42->hp_jack_in = 0;
cs42l42->mic_jack_in = 0;
break;
default:
/* jack in transition */
break;
}
codec_dbg(cs42l42->codec, "Tip Sense Detection: (%d)\n", reg_ts_status);
return status_changed;
}
static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
{
int current_plug_status;
int status_changed = 0;
int reg_cdc_status;
int reg_hs_status;
@ -678,46 +802,65 @@ static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
int type;
/* Read jack detect status registers */
reg_cdc_status = cs8409_i2c_read(cs42l42, 0x1308);
reg_hs_status = cs8409_i2c_read(cs42l42, 0x1124);
reg_ts_status = cs8409_i2c_read(cs42l42, 0x130f);
reg_cdc_status = cs8409_i2c_read(cs42l42, CS42L42_CODEC_STATUS);
reg_hs_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
reg_ts_status = cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
/* If status values are < 0, read error has occurred. */
if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
return -EIO;
current_plug_status = (reg_ts_status & (CS42L42_TS_PLUG_MASK | CS42L42_TS_UNPLUG_MASK))
>> CS42L42_TS_PLUG_SHIFT;
/* HSDET_AUTO_DONE */
if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE_MASK) {
/* Disable HSDET_AUTO_DONE */
cs8409_i2c_write(cs42l42, 0x131b, 0xFF);
cs8409_i2c_write(cs42l42, CS42L42_CODEC_INT_MASK, 0xFF);
type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
type = (reg_hs_status & CS42L42_HSDET_TYPE_MASK) >> CS42L42_HSDET_TYPE_SHIFT;
/* Configure the HSDET mode. */
cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0x80);
if (cs42l42->no_type_dect) {
status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
} else if (type == 4) {
/* Type 4 not supported */
status_changed = cs42l42_handle_tip_sense(cs42l42, CS42L42_JACK_REMOVED);
status_changed = cs42l42_handle_tip_sense(cs42l42, current_plug_status);
} else {
if (!cs42l42->hp_jack_in) {
if (type == CS42L42_PLUG_INVALID || type == CS42L42_PLUG_HEADPHONE) {
codec_dbg(cs42l42->codec,
"Auto detect value not valid (%d), running manual det\n",
type);
type = cs42l42_manual_hs_det(cs42l42);
}
switch (type) {
case CS42L42_PLUG_CTIA:
case CS42L42_PLUG_OMTP:
status_changed = 1;
cs42l42->hp_jack_in = 1;
}
/* type = 3 has no mic */
if ((!cs42l42->mic_jack_in) && (type != 3)) {
status_changed = 1;
cs42l42->mic_jack_in = 1;
break;
case CS42L42_PLUG_HEADPHONE:
status_changed = 1;
cs42l42->hp_jack_in = 1;
cs42l42->mic_jack_in = 0;
break;
default:
status_changed = 1;
cs42l42->hp_jack_in = 0;
cs42l42->mic_jack_in = 0;
break;
}
codec_dbg(cs42l42->codec, "Detection done (%d)\n", type);
}
/* Configure the HSDET mode. */
cs8409_i2c_write(cs42l42, 0x1120, 0x80);
/* Enable the HPOUT ground clamp and configure the HP pull-down */
cs8409_i2c_write(cs42l42, 0x1F06, 0x02);
cs8409_i2c_write(cs42l42, CS42L42_DAC_CTL2, 0x02);
/* Re-Enable Tip Sense Interrupt */
cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xF3);
} else {
status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
status_changed = cs42l42_handle_tip_sense(cs42l42, current_plug_status);
}
return status_changed;
@ -726,19 +869,19 @@ static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
static void cs42l42_resume(struct sub_codec *cs42l42)
{
struct hda_codec *codec = cs42l42->codec;
unsigned int gpio_data;
struct cs8409_spec *spec = codec->spec;
struct cs8409_i2c_param irq_regs[] = {
{ 0x1308, 0x00 },
{ 0x1309, 0x00 },
{ 0x130A, 0x00 },
{ 0x130F, 0x00 },
{ CS42L42_CODEC_STATUS, 0x00 },
{ CS42L42_DET_INT_STATUS1, 0x00 },
{ CS42L42_DET_INT_STATUS2, 0x00 },
{ CS42L42_TSRS_PLUG_STATUS, 0x00 },
};
int fsv_old, fsv_new;
/* Bring CS42L42 out of Reset */
gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
gpio_data |= cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
spec->gpio_data |= cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
usleep_range(10000, 15000);
cs42l42->suspended = 0;
@ -750,13 +893,13 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
/* Clear interrupts, by reading interrupt status registers */
cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
fsv_old = cs8409_i2c_read(cs42l42, 0x2001);
fsv_old = cs8409_i2c_read(cs42l42, CS42L42_HP_CTL);
if (cs42l42->full_scale_vol == CS42L42_FULL_SCALE_VOL_0DB)
fsv_new = fsv_old & ~CS42L42_FULL_SCALE_VOL_MASK;
else
fsv_new = fsv_old & CS42L42_FULL_SCALE_VOL_MASK;
if (fsv_new != fsv_old)
cs8409_i2c_write(cs42l42, 0x2001, fsv_new);
cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv_new);
/* we have to explicitly allow unsol event handling even during the
* resume phase so that the jack event is processed properly
@ -770,41 +913,40 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
static void cs42l42_suspend(struct sub_codec *cs42l42)
{
struct hda_codec *codec = cs42l42->codec;
unsigned int gpio_data;
struct cs8409_spec *spec = codec->spec;
int reg_cdc_status = 0;
const struct cs8409_i2c_param cs42l42_pwr_down_seq[] = {
{ 0x1F06, 0x02 },
{ 0x1129, 0x00 },
{ 0x2301, 0x3F },
{ 0x2302, 0x3F },
{ 0x2303, 0x3F },
{ 0x2001, 0x0F },
{ 0x2A01, 0x00 },
{ 0x1207, 0x00 },
{ 0x1101, 0xFE },
{ 0x1102, 0x8C },
{ 0x1101, 0xFF },
{ CS42L42_DAC_CTL2, 0x02 },
{ CS42L42_HS_CLAMP_DISABLE, 0x00 },
{ CS42L42_MIXER_CHA_VOL, 0x3F },
{ CS42L42_MIXER_ADC_VOL, 0x3F },
{ CS42L42_MIXER_CHB_VOL, 0x3F },
{ CS42L42_HP_CTL, 0x0F },
{ CS42L42_ASP_RX_DAI0_EN, 0x00 },
{ CS42L42_ASP_CLK_CFG, 0x00 },
{ CS42L42_PWR_CTL1, 0xFE },
{ CS42L42_PWR_CTL2, 0x8C },
{ CS42L42_PWR_CTL1, 0xFF },
};
cs8409_i2c_bulk_write(cs42l42, cs42l42_pwr_down_seq, ARRAY_SIZE(cs42l42_pwr_down_seq));
if (read_poll_timeout(cs8409_i2c_read, reg_cdc_status,
(reg_cdc_status & 0x1), CS42L42_PDN_SLEEP_US, CS42L42_PDN_TIMEOUT_US,
true, cs42l42, 0x1308) < 0)
true, cs42l42, CS42L42_CODEC_STATUS) < 0)
codec_warn(codec, "Timeout waiting for PDN_DONE for CS42L42\n");
/* Power down CS42L42 ASP/EQ/MIX/HP */
cs8409_i2c_write(cs42l42, 0x1102, 0x9C);
cs8409_i2c_write(cs42l42, CS42L42_PWR_CTL2, 0x9C);
cs42l42->suspended = 1;
cs42l42->last_page = 0;
cs42l42->hp_jack_in = 0;
cs42l42->mic_jack_in = 0;
cs42l42->force_status_change = 1;
/* Put CS42L42 into Reset */
gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
gpio_data &= ~cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
spec->gpio_data &= ~cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
}
#endif
@ -918,6 +1060,10 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
/* DMIC1_MO=00b, DMIC1/2_SR=1 */
cs8409_vendor_coef_set(codec, CS8409_DMIC_CFG, 0x0003);
break;
case CS8409_ODIN:
/* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=0 */
cs8409_vendor_coef_set(codec, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc00);
break;
default:
break;
}
@ -994,6 +1140,8 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
spec->gen.no_primary_hp = 1;
spec->gen.suppress_vmaster = 1;
spec->speaker_pdn_gpio = 0;
/* GPIO 5 out, 3,4 in */
spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio;
spec->gpio_data = 0;
@ -1005,18 +1153,33 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID);
cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID);
/* Set HSBIAS_SENSE_EN and Full Scale volume for some variants. */
spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
switch (codec->fixup_id) {
case CS8409_WARLOCK_MLK:
case CS8409_WARLOCK_MLK_DUAL_MIC:
spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_0DB;
break;
default:
spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
case CS8409_CYBORG:
spec->scodecs[CS8409_CODEC0]->full_scale_vol =
CS42L42_FULL_SCALE_VOL_MINUS6DB;
spec->speaker_pdn_gpio = CS8409_CYBORG_SPEAKER_PDN;
break;
case CS8409_ODIN:
spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_0DB;
spec->speaker_pdn_gpio = CS8409_CYBORG_SPEAKER_PDN;
break;
case CS8409_WARLOCK_MLK:
case CS8409_WARLOCK_MLK_DUAL_MIC:
spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_0DB;
spec->speaker_pdn_gpio = CS8409_WARLOCK_SPEAKER_PDN;
break;
default:
spec->scodecs[CS8409_CODEC0]->full_scale_vol =
CS42L42_FULL_SCALE_VOL_MINUS6DB;
spec->speaker_pdn_gpio = CS8409_WARLOCK_SPEAKER_PDN;
break;
}
if (spec->speaker_pdn_gpio > 0) {
spec->gpio_dir |= spec->speaker_pdn_gpio;
spec->gpio_data |= spec->speaker_pdn_gpio;
}
break;
@ -1027,13 +1190,17 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
/* add hooks */
spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
/* Set initial DMIC volume to -26 dB */
snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
HDA_INPUT, 0, 0xff, 0x19);
if (codec->fixup_id != CS8409_ODIN)
/* Set initial DMIC volume to -26 dB */
snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
HDA_INPUT, 0, 0xff, 0x19);
snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
&cs42l42_dac_volume_mixer);
snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume",
&cs42l42_adc_volume_mixer);
if (spec->speaker_pdn_gpio > 0)
snd_hda_gen_add_kctl(&spec->gen, "Speaker Playback Switch",
&cs8409_spk_sw_ctrl);
/* Disable Unsolicited Response during boot */
cs8409_enable_ur(codec, 0);
snd_hda_codec_set_name(codec, "CS8409/CS42L42");

View File

@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <sound/tlv.h>
#include <linux/workqueue.h>
#include <sound/cs42l42.h>
#include <sound/hda_codec.h>
#include "hda_local.h"
#include "hda_auto_parser.h"
@ -222,15 +223,8 @@ enum cs8409_coefficient_index_registers {
#define CS42L42_HP_VOL_REAL_MAX (0)
#define CS42L42_AMIC_VOL_REAL_MIN (-97)
#define CS42L42_AMIC_VOL_REAL_MAX (12)
#define CS42L42_REG_HS_VOL_CHA (0x2301)
#define CS42L42_REG_HS_VOL_CHB (0x2303)
#define CS42L42_REG_HS_VOL_MASK (0x003F)
#define CS42L42_REG_AMIC_VOL (0x1D03)
#define CS42L42_REG_AMIC_VOL_MASK (0x00FF)
#define CS42L42_HSDET_AUTO_DONE (0x02)
#define CS42L42_HSTYPE_MASK (0x03)
#define CS42L42_JACK_INSERTED (0x0C)
#define CS42L42_JACK_REMOVED (0x00)
#define CS42L42_I2C_TIMEOUT_US (20000)
#define CS42L42_I2C_SLEEP_US (2000)
#define CS42L42_PDN_TIMEOUT_US (250000)
@ -244,6 +238,8 @@ enum cs8409_coefficient_index_registers {
#define CS42L42_I2C_ADDR (0x48 << 1)
#define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */
#define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */
#define CS8409_CYBORG_SPEAKER_PDN GENMASK(2, 2) /* CS8409_GPIO2 */
#define CS8409_WARLOCK_SPEAKER_PDN GENMASK(1, 1) /* CS8409_GPIO1 */
#define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
#define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A
#define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
@ -273,6 +269,7 @@ enum {
CS8409_FIXUPS,
CS8409_DOLPHIN,
CS8409_DOLPHIN_FIXUPS,
CS8409_ODIN,
};
enum {
@ -310,7 +307,6 @@ struct sub_codec {
unsigned int hp_jack_in:1;
unsigned int mic_jack_in:1;
unsigned int force_status_change:1;
unsigned int suspended:1;
unsigned int paged:1;
unsigned int last_page;
@ -332,6 +328,8 @@ struct cs8409_spec {
unsigned int gpio_dir;
unsigned int gpio_data;
int speaker_pdn_gpio;
struct mutex i2c_mux;
unsigned int i2c_clck_enabled;
unsigned int dev_addr;

View File

@ -3131,6 +3131,7 @@ enum {
ALC269_TYPE_ALC257,
ALC269_TYPE_ALC215,
ALC269_TYPE_ALC225,
ALC269_TYPE_ALC245,
ALC269_TYPE_ALC287,
ALC269_TYPE_ALC294,
ALC269_TYPE_ALC300,
@ -3168,6 +3169,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
case ALC269_TYPE_ALC257:
case ALC269_TYPE_ALC215:
case ALC269_TYPE_ALC225:
case ALC269_TYPE_ALC245:
case ALC269_TYPE_ALC287:
case ALC269_TYPE_ALC294:
case ALC269_TYPE_ALC300:
@ -3695,7 +3697,8 @@ static void alc225_init(struct hda_codec *codec)
hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp1_pin_sense, hp2_pin_sense;
if (spec->codec_variant != ALC269_TYPE_ALC287)
if (spec->codec_variant != ALC269_TYPE_ALC287 &&
spec->codec_variant != ALC269_TYPE_ALC245)
/* required only at boot or S3 and S4 resume time */
if (!spec->done_hp_init ||
is_s3_resume(codec) ||
@ -6580,18 +6583,6 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
}
}
static int find_comp_by_dev_name(struct alc_spec *spec, const char *name)
{
int i;
for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
if (strcmp(spec->comps[i].name, name) == 0)
return i;
}
return -ENODEV;
}
static int comp_bind(struct device *dev)
{
struct hda_codec *cdc = dev_to_hda_codec(dev);
@ -6666,50 +6657,10 @@ static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fix
cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 4);
}
static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
struct snd_pcm_substream *sub, int action)
{
struct alc_spec *spec = cdc->spec;
unsigned int rx_slot;
int i;
switch (action) {
case HDA_GEN_PCM_ACT_PREPARE:
rx_slot = 0;
i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.0");
if (i >= 0)
spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
rx_slot = 1;
i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.1");
if (i >= 0)
spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
break;
}
comp_generic_playback_hook(hinfo, cdc, sub, action);
}
static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
int action)
{
struct device *dev = hda_codec_dev(cdc);
struct alc_spec *spec = cdc->spec;
int ret;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
component_match_add(dev, &spec->match, component_compare_dev_name,
"i2c-CLSA0100:00-cs35l41-hda.0");
component_match_add(dev, &spec->match, component_compare_dev_name,
"i2c-CLSA0100:00-cs35l41-hda.1");
ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
if (ret)
codec_err(cdc, "Fail to register component aggregator %d\n", ret);
else
spec->gen.pcm_playback_hook = alc287_legion_16achg6_playback_hook;
break;
}
cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0100", 2);
}
/* for alc295_fixup_hp_top_speakers */
@ -10148,7 +10099,10 @@ static int patch_alc269(struct hda_codec *codec)
case 0x10ec0245:
case 0x10ec0285:
case 0x10ec0289:
spec->codec_variant = ALC269_TYPE_ALC215;
if (alc_get_coef0(codec) & 0x0010)
spec->codec_variant = ALC269_TYPE_ALC245;
else
spec->codec_variant = ALC269_TYPE_ALC215;
spec->shutup = alc225_shutup;
spec->init_hook = alc225_init;
spec->gen.mixer_nid = 0;

View File

@ -561,8 +561,9 @@ static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream)
void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
{
int i;
u8 num_streams = min_t(u8, pcm->num_streams, ARRAY_SIZE(pcm->streams));
for (i = 0; bits && i < pcm->num_streams; i++) {
for (i = 0; bits && i < num_streams; i++) {
if (bits & (1 << i)) {
struct lola_stream *str = &pcm->streams[i];
if (str->substream && str->running)

View File

@ -3314,7 +3314,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
if (hdsp->io_type == RPM) {
/* RPM Bypass, Disconnect and Input switches */
for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) {
err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp));
err = snd_ctl_add(card, snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp));
if (err < 0)
return err;
}

View File

@ -14,7 +14,7 @@ menuconfig SND_SOC
If you want ASoC support, you should say Y here and also to the
specific driver for your SoC platform below.
ASoC provides power efficient ALSA support for embedded battery powered
SoC based systems like PDA's, Phones and Personal Media Players.
@ -55,6 +55,13 @@ config SND_SOC_TOPOLOGY_KUNIT_TEST
userspace applications such as pulseaudio, to prevent unnecessary
problems.
config SND_SOC_UTILS_KUNIT_TEST
tristate "KUnit tests for SoC utils"
depends on KUNIT
default KUNIT_ALL_TESTS
help
If you want to perform tests on ALSA SoC utils library say Y here.
config SND_SOC_ACPI
tristate

View File

@ -12,6 +12,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),)
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) := soc-topology-test.o
endif
ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),)
# snd-soc-test-objs := soc-utils-test.o
obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) := soc-utils-test.o
endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
endif

View File

@ -71,7 +71,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&cz_jack, NULL, 0);
&cz_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;
@ -151,7 +151,7 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&cz_jack, NULL, 0);
&cz_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;

View File

@ -80,7 +80,7 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&cz_jack, NULL, 0);
&cz_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;

View File

@ -42,7 +42,7 @@ config SND_AMD_ASOC_RENOIR
config SND_SOC_AMD_MACH_COMMON
tristate
depends on X86 && PCI && I2C && GPIOLIB
depends on X86 && PCI && I2C
select CLK_FIXED_FCH
select SND_SOC_RT5682_I2C
select SND_SOC_DMIC
@ -54,14 +54,14 @@ config SND_SOC_AMD_MACH_COMMON
config SND_SOC_AMD_LEGACY_MACH
tristate "AMD Legacy Machine Driver Support"
depends on X86 && PCI && I2C && GPIOLIB
depends on X86 && PCI && I2C
select SND_SOC_AMD_MACH_COMMON
help
This option enables legacy sound card support for ACP audio.
config SND_SOC_AMD_SOF_MACH
tristate "AMD SOF Machine Driver Support"
depends on X86 && PCI && I2C && GPIOLIB
depends on X86 && PCI && I2C
select SND_SOC_AMD_MACH_COMMON
help
This option enables SOF sound card support for ACP audio.

View File

@ -27,7 +27,6 @@ static struct acp_card_drvdata rt5682_rt1019_data = {
.hs_codec_id = RT5682,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_GB,
};
static struct acp_card_drvdata rt5682s_max_data = {
@ -37,7 +36,6 @@ static struct acp_card_drvdata rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_NONE,
};
static struct acp_card_drvdata rt5682s_rt1019_data = {
@ -47,7 +45,6 @@ static struct acp_card_drvdata rt5682s_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_NONE,
};
static const struct snd_kcontrol_new acp_controls[] = {
@ -62,16 +59,15 @@ static const struct snd_kcontrol_new acp_controls[] = {
static const struct snd_soc_dapm_widget acp_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Left Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Right Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
static int acp_asoc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
unsigned int spkr_gpio;
int ret;
if (!pdev->id_entry)
@ -89,20 +85,9 @@ static int acp_asoc_probe(struct platform_device *pdev)
card->controls = acp_controls;
card->num_controls = ARRAY_SIZE(acp_controls);
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
spkr_gpio = ((struct acp_card_drvdata *)(card->drvdata))->gpio_spkr_en;
acp_legacy_dai_links_create(card);
if (gpio_is_valid(spkr_gpio)) {
ret = devm_gpio_request(dev, spkr_gpio, "spkren");
if (ret) {
dev_err(dev, "(%s) gpio request failed: %d\n",
__func__, ret);
return ret;
}
gpio_direction_output(spkr_gpio, 0);
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev,
@ -131,6 +116,7 @@ static const struct platform_device_id board_ids[] = {
};
static struct platform_driver acp_asoc_audio = {
.driver = {
.pm = &snd_soc_pm_ops,
.name = "acp_mach",
},
.probe = acp_asoc_probe,

View File

@ -71,31 +71,6 @@ static const struct snd_soc_dapm_route rt5682_map[] = {
{ "IN1P", NULL, "Headset Mic" },
};
int event_spkr_handler(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct acp_card_drvdata *drvdata = snd_soc_card_get_drvdata(card);
if (!gpio_is_valid(drvdata->gpio_spkr_en))
return 0;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
gpio_set_value(drvdata->gpio_spkr_en, 1);
break;
case SND_SOC_DAPM_PRE_PMD:
gpio_set_value(drvdata->gpio_spkr_en, 0);
break;
default:
dev_warn(card->dev, "%s invalid setting\n", __func__);
break;
}
return 0;
}
EXPORT_SYMBOL_NS_GPL(event_spkr_handler, SND_SOC_AMD_MACH);
/* Define card ops for RT5682 CODEC */
static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
@ -145,7 +120,7 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pco_jack, NULL, 0);
&pco_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;
@ -266,7 +241,7 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pco_jack, NULL, 0);
&pco_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;

View File

@ -17,11 +17,6 @@
#include <linux/input.h>
#include <linux/module.h>
#include <sound/soc.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#define EN_SPKR_GPIO_GB 0x11F
#define EN_SPKR_GPIO_NONE -EINVAL
enum be_id {
HEADSET_BE_ID = 0,
@ -54,11 +49,9 @@ struct acp_card_drvdata {
unsigned int dai_fmt;
struct clk *wclk;
struct clk *bclk;
unsigned int gpio_spkr_en;
};
int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
int acp_legacy_dai_links_create(struct snd_soc_card *card);
int event_spkr_handler(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event);
#endif

View File

@ -27,7 +27,6 @@ static struct acp_card_drvdata sof_rt5682_rt1019_data = {
.hs_codec_id = RT5682,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_GB,
};
static struct acp_card_drvdata sof_rt5682_max_data = {
@ -37,7 +36,6 @@ static struct acp_card_drvdata sof_rt5682_max_data = {
.hs_codec_id = RT5682,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_NONE,
};
static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
@ -56,7 +54,6 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.gpio_spkr_en = EN_SPKR_GPIO_NONE,
};
static const struct snd_kcontrol_new acp_controls[] = {
@ -70,16 +67,15 @@ static const struct snd_kcontrol_new acp_controls[] = {
static const struct snd_soc_dapm_widget acp_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Left Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Right Spk", event_spkr_handler),
SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
static int acp_sof_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
unsigned int spkr_gpio;
int ret;
if (!pdev->id_entry)
@ -97,20 +93,9 @@ static int acp_sof_probe(struct platform_device *pdev)
card->controls = acp_controls;
card->num_controls = ARRAY_SIZE(acp_controls);
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
spkr_gpio = ((struct acp_card_drvdata *)(card->drvdata))->gpio_spkr_en;
acp_sofdsp_dai_links_create(card);
if (gpio_is_valid(spkr_gpio)) {
ret = devm_gpio_request(dev, spkr_gpio, "spkren");
if (ret) {
dev_err(dev, "(%s) gpio request failed: %d\n",
__func__, ret);
return ret;
}
gpio_direction_output(spkr_gpio, 0);
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev,
@ -144,6 +129,7 @@ static const struct platform_device_id board_ids[] = {
static struct platform_driver acp_asoc_audio = {
.driver = {
.name = "sof_mach",
.pm = &snd_soc_pm_ops,
},
.probe = acp_sof_probe,
.id_table = board_ids,

View File

@ -90,7 +90,7 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pco_jack, NULL, 0);
&pco_jack);
if (ret) {
dev_err(card->dev, "HP jack creation failed %d\n", ret);
return ret;

View File

@ -17,10 +17,8 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
@ -61,10 +59,10 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd)
* Headset buttons map to the google Reference headset.
* These can be configured by userspace.
*/
ret = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_BTN_0,
&vg_headset, acp5x_nau8821_jack_pins,
ARRAY_SIZE(acp5x_nau8821_jack_pins));
ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_BTN_0,
&vg_headset, acp5x_nau8821_jack_pins,
ARRAY_SIZE(acp5x_nau8821_jack_pins));
if (ret) {
dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
return ret;

View File

@ -12,6 +12,7 @@
#include <sound/pcm_params.h>
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
#include "acp6x.h"
@ -45,108 +46,126 @@ static struct snd_soc_card acp6x_card = {
static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D2"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D3"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D4"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D5"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CF"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CG"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CQ"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CR"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21AW"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21AX"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21BN"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21BQ"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CH"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CJ"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CK"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D8"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D9"),
@ -157,18 +176,33 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
static int acp6x_probe(struct platform_device *pdev)
{
const struct dmi_system_id *dmi_id;
struct acp6x_pdm *machine = NULL;
struct snd_soc_card *card;
struct acpi_device *adev;
int ret;
const struct dmi_system_id *dmi_id;
/* check the parent device's firmware node has _DSD or not */
adev = ACPI_COMPANION(pdev->dev.parent);
if (adev) {
const union acpi_object *obj;
if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == 1)
platform_set_drvdata(pdev, &acp6x_card);
}
/* check for any DMI overrides */
dmi_id = dmi_first_match(yc_acp_quirk_table);
if (!dmi_id)
if (dmi_id)
platform_set_drvdata(pdev, dmi_id->driver_data);
card = platform_get_drvdata(pdev);
if (!card)
return -ENODEV;
card = &acp6x_card;
dev_info(&pdev->dev, "Enabling ACP DMIC support via %s", dmi_id ? "DMI" : "ACPI");
acp6x_card.dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {

Some files were not shown because too many files have changed in this diff Show More