Merge branch 'for-linus' into for-next
Pull pending ASoC and HD-audio fixes for 6.14-rc1 Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
7bba999e93
20 changed files with 418 additions and 36 deletions
Documentation/sound
MAINTAINERSinclude/sound
sound
core/seq
pci/hda
soc
codecs
generic
intel/boards
renesas/rcar
samsung
usb
292
Documentation/sound/codecs/cs35l56.rst
Normal file
292
Documentation/sound/codecs/cs35l56.rst
Normal file
|
@ -0,0 +1,292 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
=====================================================================
|
||||
Audio drivers for Cirrus Logic CS35L54/56/57 Boosted Smart Amplifiers
|
||||
=====================================================================
|
||||
:Copyright: 2025 Cirrus Logic, Inc. and
|
||||
Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
Contact: patches@opensource.cirrus.com
|
||||
|
||||
Summary
|
||||
=======
|
||||
|
||||
The high-level summary of this document is:
|
||||
|
||||
**If you have a laptop that uses CS35L54/56/57 amplifiers but audio is not
|
||||
working, DO NOT ATTEMPT TO USE FIRMWARE AND SETTINGS FROM ANOTHER LAPTOP,
|
||||
EVEN IF THAT LAPTOP SEEMS SIMILAR.**
|
||||
|
||||
The CS35L54/56/57 amplifiers must be correctly configured for the power
|
||||
supply voltage, speaker impedance, maximum speaker voltage/current, and
|
||||
other external hardware connections.
|
||||
|
||||
The amplifiers feature advanced boost technology that increases the voltage
|
||||
used to drive the speakers, while proprietary speaker protection algorithms
|
||||
allow these boosted amplifiers to push the limits of the speakers without
|
||||
causing damage. These **must** be configured correctly.
|
||||
|
||||
Supported Cirrus Logic amplifiers
|
||||
---------------------------------
|
||||
|
||||
The cs35l56 drivers support:
|
||||
|
||||
* CS35L54
|
||||
* CS35L56
|
||||
* CS35L57
|
||||
|
||||
There are two drivers in the kernel
|
||||
|
||||
*For systems using SoundWire*: sound/soc/codecs/cs35l56.c and associated files
|
||||
|
||||
*For systems using HDA*: sound/pci/hda/cs35l56_hda.c
|
||||
|
||||
Firmware
|
||||
========
|
||||
|
||||
The amplifier is controlled and managed by firmware running on the internal
|
||||
DSP. Firmware files are essential to enable the full capabilities of the
|
||||
amplifier.
|
||||
|
||||
Firmware is distributed in the linux-firmware repository:
|
||||
https://gitlab.com/kernel-firmware/linux-firmware.git
|
||||
|
||||
On most SoundWire systems the amplifier has a default minimum capability to
|
||||
produce audio. However this will be
|
||||
|
||||
* at low volume, to protect the speakers, since the speaker specifications
|
||||
and power supply voltages are unknown.
|
||||
* a mono mix of left and right channels.
|
||||
|
||||
On some SoundWire systems that have both CS42L43 and CS35L56/57 the CS35L56/57
|
||||
receive their audio from the CS42L43 instead of directly from the host
|
||||
SoundWire interface. These systems can be identified by the CS42L43 showing
|
||||
in dmesg as a SoundWire device, but the CS35L56/57 as SPI. On these systems
|
||||
the firmware is *mandatory* to enable receiving the audio from the CS42L43.
|
||||
|
||||
On HDA systems the firmware is *mandatory* to enable HDA bridge mode. There
|
||||
will not be any audio from the amplifiers without firmware.
|
||||
|
||||
Cirrus Logic firmware files
|
||||
---------------------------
|
||||
|
||||
Each amplifier requires two firmware files. One file has a .wmfw suffix, the
|
||||
other has a .bin suffix.
|
||||
|
||||
The firmware is customized by the OEM to match the hardware of each laptop,
|
||||
and the firmware is specific to that laptop. Because of this, there are many
|
||||
firmware files in linux-firmware for these amplifiers. Firmware files are
|
||||
**not interchangeable between laptops**.
|
||||
|
||||
Cirrus Logic submits files for known laptops to the upstream linux-firmware
|
||||
repository. Providing Cirrus Logic is aware of a particular laptop and has
|
||||
permission from the manufacturer to publish the firmware, it will be pushed
|
||||
to linux-firmware. You may need to upgrade to a newer release of
|
||||
linux-firmware to obtain the firmware for your laptop.
|
||||
|
||||
**Important:** the Makefile for linux-firmware creates symlinks that are listed
|
||||
in the WHENCE file. These symlinks are required for the CS35L56 driver to be
|
||||
able to load the firmware.
|
||||
|
||||
How do I know which firmware file I should have?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
All firmware file names are qualified with a unique "system ID". On normal
|
||||
x86 PCs with PCI audio this is the Vendor Subsystem ID (SSID) of the host
|
||||
PCI audio interface.
|
||||
|
||||
The SSID can be viewed using the lspci tool::
|
||||
|
||||
lspci -v -nn | grep -A2 -i audio
|
||||
0000:00:1f.3 Audio device [0403]: Intel Corporation Meteor Lake-P HD Audio Controller [8086:7e28]
|
||||
Subsystem: Dell Meteor Lake-P HD Audio Controller [1028:0c63]
|
||||
|
||||
In this example the SSID is 10280c63.
|
||||
|
||||
The format of the firmware file names is:
|
||||
|
||||
cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN
|
||||
|
||||
Where:
|
||||
|
||||
* cs35lxx-b0 is the amplifier model and silicon revision. This information
|
||||
is logged by the driver during initialization.
|
||||
* SSID is the 8-digit hexadecimal SSID value.
|
||||
* ampN is the amplifier number (for example amp1). This is the same as
|
||||
the prefix on the ALSA control names except that it is always lower-case
|
||||
in the file name.
|
||||
* spkidX is an optional part, used for laptops that have firmware
|
||||
configurations for different makes and models of internal speakers.
|
||||
|
||||
Sound Open Firmware and ALSA topology files
|
||||
-------------------------------------------
|
||||
|
||||
All SoundWire systems will require a Sound Open Firmware (SOF) for the
|
||||
host CPU audio DSP, together with an ALSA topology file (.tplg).
|
||||
|
||||
The SOF firmware will usually be provided by the manufacturer of the host
|
||||
CPU (i.e. Intel or AMD). The .tplg file is normally part of the SOF firmware
|
||||
release.
|
||||
|
||||
SOF binary builds are available from: https://github.com/thesofproject/sof-bin/releases
|
||||
|
||||
The main SOF source is here: https://github.com/thesofproject
|
||||
|
||||
ALSA-ucm configurations
|
||||
-----------------------
|
||||
Typically an appropriate ALSA-ucm configuration file is needed for
|
||||
use-case managers and audio servers such as PipeWire.
|
||||
|
||||
Configuration files are available from the alsa-ucm-conf repository:
|
||||
https://git.alsa-project.org/?p=alsa-ucm-conf.git
|
||||
|
||||
Kernel log messages
|
||||
===================
|
||||
|
||||
SoundWire
|
||||
---------
|
||||
A successful initialization will look like this (this will be repeated for
|
||||
each amplifier)::
|
||||
|
||||
[ 7.568374] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_P not found, using dummy regulator
|
||||
[ 7.605208] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_IO not found, using dummy regulator
|
||||
[ 7.605313] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_A not found, using dummy regulator
|
||||
[ 7.939279] cs35l56 sdw:0:0:01fa:3556:01:0: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0)
|
||||
[ 7.947844] cs35l56 sdw:0:0:01fa:3556:01:0: Slave 4 state check1: UNATTACHED, status was 1
|
||||
[ 8.740280] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_B not found, using dummy regulator
|
||||
[ 8.740552] cs35l56 sdw:0:0:01fa:3556:01:0: supply VDD_AMP not found, using dummy regulator
|
||||
[ 9.242164] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: format 3 timestamp 0x66b2b872
|
||||
[ 9.242173] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: Tue 05 Dec 2023 21:37:21 GMT Standard Time
|
||||
[ 9.991709] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: Firmware: 1a00d6 vendor: 0x2 v3.11.23, 41 algorithms
|
||||
[10.039098] cs35l56 sdw:0:0:01fa:3556:01:0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin: v3.11.23
|
||||
[10.879235] cs35l56 sdw:0:0:01fa:3556:01:0: Slave 4 state check1: UNATTACHED, status was 1
|
||||
[11.401536] cs35l56 sdw:0:0:01fa:3556:01:0: Calibration applied
|
||||
|
||||
HDA
|
||||
---
|
||||
A successful initialization will look like this (this will be repeated for
|
||||
each amplifier)::
|
||||
|
||||
[ 6.306475] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0)
|
||||
[ 6.613892] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP system name: 'xxxxxxxx', amp name: 'AMP1'
|
||||
[ 8.266660] snd_hda_codec_cs8409 ehdaudio0D0: bound i2c-CSC3556:00-cs35l56-hda.0 (ops cs35l56_hda_comp_ops [snd_hda_scodec_cs35l56])
|
||||
[ 8.287525] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: format 3 timestamp 0x66b2b872
|
||||
[ 8.287528] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw: Tue 05 Dec 2023 21:37:21 GMT Standard Time
|
||||
[ 9.984335] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: Firmware: 1a00d6 vendor: 0x2 v3.11.23, 41 algorithms
|
||||
[10.085797] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin: v3.11.23
|
||||
[10.655237] cs35l56-hda i2c-CSC3556:00-cs35l56-hda.0: Calibration applied
|
||||
|
||||
Important messages
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Cirrus Logic CS35L56 Rev B0 OTP3 fw:3.4.4 (patched=0)
|
||||
Shows that the driver has been able to read device ID registers from the
|
||||
amplifier.
|
||||
|
||||
* The actual amplifier type and silicon revision (CS35L56 B0 in this
|
||||
example) is shown, as read from the amplifier identification registers.
|
||||
* (patched=0) is normal, and indicates that the amplifier has been hard
|
||||
reset and is running default ROM firmware.
|
||||
* (patched=1) means that something has previously downloaded firmware
|
||||
to the amplifier and the driver does not have control of the RESET
|
||||
signal to be able to replace this preloaded firmware. This is normal
|
||||
for systems where the BIOS downloads firmware to the amplifiers
|
||||
before OS boot.
|
||||
This status can also be seen if the cs35l56 kernel module is unloaded
|
||||
and reloaded on a system where the driver does not have control of
|
||||
RESET. SoundWire systems typically do not give the driver control of
|
||||
RESET and only a BIOS (re)boot can reset the amplifiers.
|
||||
|
||||
DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx.wmfw
|
||||
Shows that a .wmfw firmware file was found and downloaded.
|
||||
|
||||
DSP1: cirrus/cs35l56-b0-dsp1-misc-xxxxxxxx-amp1.bin
|
||||
Shows that a .bin firmware file was found and downloaded.
|
||||
|
||||
Calibration applied
|
||||
Factory calibration data in EFI was written to the amplifier.
|
||||
|
||||
Error messages
|
||||
==============
|
||||
This section explains some of the error messages that the driver can log.
|
||||
|
||||
Algorithm coefficient version %d.%d.%d but expected %d.%d.%d
|
||||
The version of the .bin file content does not match the loaded firmware.
|
||||
Caused by mismatched .wmfw and .bin file, or .bin file was found but
|
||||
.wmfw was not.
|
||||
|
||||
No %s for algorithm %x
|
||||
The version of the .bin file content does not match the loaded firmware.
|
||||
Caused by mismatched .wmfw and .bin file, or .bin file was found but
|
||||
.wmfw was not.
|
||||
|
||||
.bin file required but not found
|
||||
HDA driver did not find a .bin file that matches this hardware.
|
||||
|
||||
Calibration disabled due to missing firmware controls
|
||||
Driver was not able to write EFI calibration data to firmware registers.
|
||||
This typically means that either:
|
||||
|
||||
* The driver did not find a suitable wmfw for this hardware, or
|
||||
* The amplifier has already been patched with firmware by something
|
||||
previously, and the driver does not have control of a hard RESET line
|
||||
to be able to reset the amplifier and download the firmware files it
|
||||
found. This situation is indicated by the device identification
|
||||
string in the kernel log shows "(patched=1)"
|
||||
|
||||
Failed to write calibration
|
||||
Same meaning and cause as "Calibration disabled due to missing firmware
|
||||
controls"
|
||||
|
||||
Failed to read calibration data from EFI
|
||||
Factory calibration data in EFI is missing, empty or corrupt.
|
||||
This is most likely to be cause by accidentally deleting the file from
|
||||
the EFI filesystem.
|
||||
|
||||
No calibration for silicon ID
|
||||
The factory calibration data in EFI does not match this hardware.
|
||||
The most likely cause is that an amplifier has been replaced on the
|
||||
motherboard without going through manufacturer calibration process to
|
||||
generate calibration data for the new amplifier.
|
||||
|
||||
Did not find any buses for CSCxxxx
|
||||
Only on HDA systems. The HDA codec driver found an ACPI entry for
|
||||
Cirrus Logic companion amps, but could not enumerate the ACPI entries for
|
||||
the I2C/SPI buses. The most likely cause of this is that:
|
||||
|
||||
* The relevant bus driver (I2C or SPI) is not part of the kernel.
|
||||
* The HDA codec driver was built-in to the kernel but the I2C/SPI
|
||||
bus driver is a module and so the HDA codec driver cannot call the
|
||||
bus driver functions.
|
||||
|
||||
init_completion timed out
|
||||
The SoundWire bus controller (host end) did not enumerate the amplifier.
|
||||
In other words, the ACPI says there is an amplifier but for some reason
|
||||
it was not detected on the bus.
|
||||
|
||||
No AF01 node
|
||||
Indicates an error in ACPI. A SoundWire system should have a Device()
|
||||
node named "AF01" but it was not found.
|
||||
|
||||
Failed to get spk-id-gpios
|
||||
ACPI says that the driver should request a GPIO but the driver was not
|
||||
able to get that GPIO. The most likely cause is that the kernel does not
|
||||
include the correct GPIO or PINCTRL driver for this system.
|
||||
|
||||
Failed to read spk-id
|
||||
ACPI says that the driver should request a GPIO but the driver was not
|
||||
able to read that GPIO.
|
||||
|
||||
Unexpected spk-id element count
|
||||
AF01 contains more speaker ID GPIO entries than the driver supports
|
||||
|
||||
Overtemp error
|
||||
Amplifier overheat protection was triggered and the amplifier shut down
|
||||
to protect itself.
|
||||
|
||||
Amp short error
|
||||
Amplifier detected a short-circuit on the speaker output pins and shut
|
||||
down for protection. This would normally indicate a damaged speaker.
|
||||
|
||||
Hibernate wake failed
|
||||
The driver tried to wake the amplifier from its power-saving state but
|
||||
did not see the expected responses from the amplifier. This can be caused
|
||||
by using firmware that does not match the hardware.
|
9
Documentation/sound/codecs/index.rst
Normal file
9
Documentation/sound/codecs/index.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Codec-Specific Information
|
||||
==========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
cs35l56
|
|
@ -13,6 +13,7 @@ Sound Subsystem Documentation
|
|||
alsa-configuration
|
||||
hd-audio/index
|
||||
cards/index
|
||||
codecs/index
|
||||
utimers
|
||||
|
||||
.. only:: subproject and html
|
||||
|
|
|
@ -5469,6 +5469,7 @@ L: linux-sound@vger.kernel.org
|
|||
L: patches@opensource.cirrus.com
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/cirrus,cs*
|
||||
F: Documentation/sound/codecs/cs*
|
||||
F: drivers/mfd/cs42l43*
|
||||
F: drivers/pinctrl/cirrus/pinctrl-cs42l43*
|
||||
F: drivers/spi/spi-cs42l43*
|
||||
|
@ -21993,6 +21994,7 @@ W: https://github.com/thesofproject/linux/
|
|||
F: sound/soc/sof/
|
||||
|
||||
SOUND - GENERIC SOUND CARD (Simple-Audio-Card, Audio-Graph-Card)
|
||||
M: Mark Brown <broonie@kernel.org>
|
||||
M: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
S: Supported
|
||||
L: linux-sound@vger.kernel.org
|
||||
|
|
|
@ -89,6 +89,13 @@ struct simple_util_priv {
|
|||
#define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i)
|
||||
#define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i)
|
||||
|
||||
/* has the same effect as simple_priv_to_props(). Preferred over
|
||||
* simple_priv_to_props() when dealing with PCM runtime data as
|
||||
* the ID stored in rtd->id may not be a valid array index.
|
||||
*/
|
||||
#define runtime_simple_priv_to_props(priv, rtd) \
|
||||
((priv)->dai_props + ((rtd)->dai_link - (priv)->dai_link))
|
||||
|
||||
#define for_each_prop_dlc_cpus(props, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.cpus) && \
|
||||
|
|
|
@ -1275,10 +1275,16 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
|
|||
if (client->type != client_info->type)
|
||||
return -EINVAL;
|
||||
|
||||
/* check validity of midi_version field */
|
||||
if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3) &&
|
||||
client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
|
||||
return -EINVAL;
|
||||
if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3)) {
|
||||
/* check validity of midi_version field */
|
||||
if (client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
|
||||
return -EINVAL;
|
||||
|
||||
/* check if UMP is supported in kernel */
|
||||
if (!IS_ENABLED(CONFIG_SND_SEQ_UMP) &&
|
||||
client_info->midi_version > 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* fill the info fields */
|
||||
if (client_info->name[0])
|
||||
|
|
|
@ -10184,6 +10184,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1360, "Acer Aspire A115", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x141f, "Acer Spin SP513-54N", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
|
@ -10669,6 +10670,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x1e1f, "ASUS Vivobook 15 X1504VAP", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
|
||||
SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
@ -10958,8 +10961,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x38e0, "Yoga Y990 Intel VECO Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38f8, "Yoga Book 9i", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
|
||||
|
@ -10989,6 +10992,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x9e56, "Lenovo ZhaoYang CF4620Z", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1849, 0x0269, "Positivo Master C6400", ALC269VB_FIXUP_ASUS_ZENBOOK),
|
||||
SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK),
|
||||
SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
|
||||
|
@ -11023,6 +11027,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
|
||||
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
|
||||
|
|
|
@ -2451,6 +2451,7 @@ config SND_SOC_WM8993
|
|||
|
||||
config SND_SOC_WM8994
|
||||
tristate
|
||||
depends on MFD_WM8994
|
||||
|
||||
config SND_SOC_WM8995
|
||||
tristate
|
||||
|
|
|
@ -2404,6 +2404,7 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
|
|||
|
||||
static const struct dev_pm_ops cs42l43_codec_pm_ops = {
|
||||
RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static const struct platform_device_id cs42l43_codec_id_table[] = {
|
||||
|
|
|
@ -39,7 +39,9 @@ struct es8316_priv {
|
|||
struct snd_soc_jack *jack;
|
||||
int irq;
|
||||
unsigned int sysclk;
|
||||
unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios)];
|
||||
/* ES83xx supports halving the MCLK so it supports twice as many rates
|
||||
*/
|
||||
unsigned int allowed_rates[ARRAY_SIZE(supported_mclk_lrck_ratios) * 2];
|
||||
struct snd_pcm_hw_constraint_list sysclk_constraints;
|
||||
bool jd_inverted;
|
||||
};
|
||||
|
@ -386,6 +388,12 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|||
|
||||
if (freq % ratio == 0)
|
||||
es8316->allowed_rates[count++] = freq / ratio;
|
||||
|
||||
/* We also check if the halved MCLK produces a valid rate
|
||||
* since the codec supports halving the MCLK.
|
||||
*/
|
||||
if ((freq / ratio) % 2 == 0)
|
||||
es8316->allowed_rates[count++] = freq / ratio / 2;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
|
|
|
@ -616,7 +616,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
|
|||
0x0F, 0x0F);
|
||||
if (es8326->version > ES8326_VERSION_B) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -631,6 +631,8 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
|
|||
regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r);
|
||||
es8326->calibrated = true;
|
||||
}
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0x00);
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x00);
|
||||
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x01);
|
||||
usleep_range(1000, 5000);
|
||||
|
@ -645,7 +647,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
|
|||
} else {
|
||||
msleep(300);
|
||||
if (es8326->version > ES8326_VERSION_B) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x50);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x70);
|
||||
regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x00);
|
||||
}
|
||||
regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE,
|
||||
|
@ -676,6 +678,10 @@ static int es8326_set_bias_level(struct snd_soc_component *codec,
|
|||
regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00);
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x20);
|
||||
regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x00);
|
||||
if (es8326->version > ES8326_VERSION_B) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x30);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
|
@ -683,6 +689,12 @@ static int es8326_set_bias_level(struct snd_soc_component *codec,
|
|||
regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b);
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00);
|
||||
regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT);
|
||||
if (es8326->version > ES8326_VERSION_B) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10);
|
||||
}
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_INV, 0xc0, 0xc0);
|
||||
regmap_update_bits(es8326->regmap, ES8326_CLK_MUX, 0x80, 0x80);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
clk_disable_unprepare(es8326->mclk);
|
||||
|
@ -773,7 +785,10 @@ static void es8326_jack_button_handler(struct work_struct *work)
|
|||
case 0x6f:
|
||||
case 0x4b:
|
||||
/* button volume up */
|
||||
cur_button = SND_JACK_BTN_1;
|
||||
if ((iface == 0x6f) && (es8326->version > ES8326_VERSION_B))
|
||||
cur_button = SND_JACK_BTN_0;
|
||||
else
|
||||
cur_button = SND_JACK_BTN_1;
|
||||
break;
|
||||
case 0x27:
|
||||
/* button volume down */
|
||||
|
@ -1082,7 +1097,7 @@ static void es8326_init(struct snd_soc_component *component)
|
|||
regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66);
|
||||
es8326_disable_micbias(es8326->component);
|
||||
if (es8326->version > ES8326_VERSION_B) {
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x13);
|
||||
regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x10);
|
||||
regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
|
||||
}
|
||||
|
||||
|
|
|
@ -368,13 +368,13 @@ static const struct snd_kcontrol_new nau8824_snd_controls[] = {
|
|||
SOC_ENUM("DAC Oversampling Rate", nau8824_dac_oversampl_enum),
|
||||
|
||||
SOC_SINGLE_TLV("Speaker Right DACR Volume",
|
||||
NAU8824_REG_CLASSD_GAIN_1, 8, 0x1f, 0, spk_vol_tlv),
|
||||
NAU8824_REG_CLASSD_GAIN_1, 8, 0x19, 0, spk_vol_tlv),
|
||||
SOC_SINGLE_TLV("Speaker Left DACL Volume",
|
||||
NAU8824_REG_CLASSD_GAIN_2, 0, 0x1f, 0, spk_vol_tlv),
|
||||
NAU8824_REG_CLASSD_GAIN_2, 0, 0x19, 0, spk_vol_tlv),
|
||||
SOC_SINGLE_TLV("Speaker Left DACR Volume",
|
||||
NAU8824_REG_CLASSD_GAIN_1, 0, 0x1f, 0, spk_vol_tlv),
|
||||
NAU8824_REG_CLASSD_GAIN_1, 0, 0x19, 0, spk_vol_tlv),
|
||||
SOC_SINGLE_TLV("Speaker Right DACL Volume",
|
||||
NAU8824_REG_CLASSD_GAIN_2, 8, 0x1f, 0, spk_vol_tlv),
|
||||
NAU8824_REG_CLASSD_GAIN_2, 8, 0x19, 0, spk_vol_tlv),
|
||||
|
||||
SOC_SINGLE_TLV("Headphone Right DACR Volume",
|
||||
NAU8824_REG_ATT_PORT0, 8, 0x1f, 0, hp_vol_tlv),
|
||||
|
|
|
@ -78,7 +78,7 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = {
|
|||
X2781_CL_STT_VAL(TAS2781_PRM_INT_MASK_REG, 0xfe, false),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_CLK_CFG_REG, 0xdd, false),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_RSVD_REG, 0x20, false),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, false),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, true),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_TEST_62_REG, 0x45, true),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_PVDD_UVLO_REG, 0x03, false),
|
||||
X2781_CL_STT_VAL(TAS2781_PRM_CHNL_0_REG, 0xa8, false),
|
||||
|
|
|
@ -296,7 +296,7 @@ int simple_util_startup(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
|
||||
struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
|
||||
struct simple_util_dai *dai;
|
||||
unsigned int fixed_sysclk = 0;
|
||||
int i1, i2, i;
|
||||
|
@ -357,7 +357,7 @@ void simple_util_shutdown(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
|
||||
struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
|
||||
struct simple_util_dai *dai;
|
||||
int i;
|
||||
|
||||
|
@ -448,7 +448,7 @@ int simple_util_hw_params(struct snd_pcm_substream *substream,
|
|||
struct simple_util_dai *pdai;
|
||||
struct snd_soc_dai *sdai;
|
||||
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
|
||||
struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
|
||||
unsigned int mclk, mclk_fs = 0;
|
||||
int i, ret;
|
||||
|
||||
|
@ -517,7 +517,7 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->id);
|
||||
struct simple_dai_props *dai_props = runtime_simple_priv_to_props(priv, rtd);
|
||||
struct simple_util_data *data = &dai_props->adata;
|
||||
struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||
struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
@ -628,7 +628,7 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd,
|
|||
int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
|
||||
struct simple_dai_props *props = runtime_simple_priv_to_props(priv, rtd);
|
||||
struct simple_util_dai *dai;
|
||||
int i, ret;
|
||||
|
||||
|
|
|
@ -608,17 +608,32 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "3838")
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "83JX")
|
||||
},
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "3832")
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "83LC")
|
||||
},
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "83MC")
|
||||
},
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
|
||||
}, {
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "83NM")
|
||||
},
|
||||
.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
|
|
|
@ -374,12 +374,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
||||
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
||||
{
|
||||
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
|
||||
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
|
||||
struct clk *clk;
|
||||
int i;
|
||||
int ret = 0, i;
|
||||
|
||||
if (enable) {
|
||||
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
|
||||
|
@ -389,18 +389,33 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
|||
|
||||
for_each_rsnd_clkin(clk, adg, i) {
|
||||
if (enable) {
|
||||
clk_prepare_enable(clk);
|
||||
ret = clk_prepare_enable(clk);
|
||||
|
||||
/*
|
||||
* We shouldn't use clk_get_rate() under
|
||||
* atomic context. Let's keep it when
|
||||
* rsnd_adg_clk_enable() was called
|
||||
*/
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
adg->clkin_rate[i] = clk_get_rate(clk);
|
||||
} else {
|
||||
clk_disable_unprepare(clk);
|
||||
if (adg->clkin_rate[i])
|
||||
clk_disable_unprepare(clk);
|
||||
|
||||
adg->clkin_rate[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rsnd_adg_clk_enable() might return error (_disable() will not).
|
||||
* We need to rollback in such case
|
||||
*/
|
||||
if (ret < 0)
|
||||
rsnd_adg_clk_disable(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
|
||||
|
@ -753,7 +768,10 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsnd_adg_clk_enable(priv);
|
||||
ret = rsnd_adg_clk_enable(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsnd_adg_clk_dbg_info(priv, NULL);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2086,9 +2086,7 @@ static int __maybe_unused rsnd_resume(struct device *dev)
|
|||
{
|
||||
struct rsnd_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
rsnd_adg_clk_enable(priv);
|
||||
|
||||
return 0;
|
||||
return rsnd_adg_clk_enable(priv);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rsnd_pm_ops = {
|
||||
|
|
|
@ -608,7 +608,7 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
|
|||
struct rsnd_dai_stream *io);
|
||||
#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
|
||||
#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
|
||||
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
|
||||
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
|
||||
void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
|
||||
|
||||
/*
|
||||
|
|
|
@ -127,8 +127,9 @@ config SND_SOC_SAMSUNG_TM2_WM5110
|
|||
|
||||
config SND_SOC_SAMSUNG_ARIES_WM8994
|
||||
tristate "SoC I2S Audio support for WM8994 on Aries"
|
||||
depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON
|
||||
depends on SND_SOC_SAMSUNG && I2C && IIO && EXTCON
|
||||
select SND_SOC_BT_SCO
|
||||
select MFD_WM8994
|
||||
select SND_SOC_WM8994
|
||||
select SND_SAMSUNG_I2S
|
||||
help
|
||||
|
@ -140,8 +141,9 @@ config SND_SOC_SAMSUNG_ARIES_WM8994
|
|||
|
||||
config SND_SOC_SAMSUNG_MIDAS_WM1811
|
||||
tristate "SoC I2S Audio support for Midas boards"
|
||||
depends on SND_SOC_SAMSUNG && IIO
|
||||
depends on SND_SOC_SAMSUNG && I2C && IIO
|
||||
select SND_SAMSUNG_I2S
|
||||
select MFD_WM8994
|
||||
select SND_SOC_WM8994
|
||||
help
|
||||
Say Y if you want to add support for SoC audio on the Midas boards.
|
||||
|
|
|
@ -2239,6 +2239,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
|||
QUIRK_FLAG_CTL_MSG_DELAY_1M),
|
||||
DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */
|
||||
QUIRK_FLAG_CTL_MSG_DELAY_1M),
|
||||
DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
|
||||
QUIRK_FLAG_FIXED_RATE),
|
||||
DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
|
||||
|
|
Loading…
Add table
Reference in a new issue