sound fixes for 6.19

A collection of small fixes.  It became a bit larger than wished,
 but all of them are device-specific small fixes, and it should be
 still fairly safe to take at the last minute.
 
 Included are a few quirks and fixes for Intel, AMD, HD-audio, and
 USB-audio, as well as a race fix in aloop driver and corrections
 of Cirrus firmware kunit test
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmmFtrEOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE+5qw//ZMzL++FkmAkZV+EHF6XqAaGd1PlA14s13Nzm
 +lDV8XqM1N5W3LIhUpANEf+DZB+9P/uy2IJqz7rCMAe5JiTdiovUplKg6VIwq1Y7
 vemglGR1Y/nzxgAYtjI8H6F30mx/tufFRP3UXv4eKu20CwX5wK/AJwS71WKdjiXI
 YSeTtjhnkzVHiqvloDupZj7TI+jXD/1aHI0HebWs9NQmBHoZwLsDRY81ajUGEqvJ
 0YWzCu08k3D7M4BB6W5gGDjuR2sSl6mIMU2g9erRu9Gbg4g82q5FCs1VKnmrDtCz
 UW3TRfdFI7/h9G2uJE7Go15LjgxzmotAEJNzgmy8cDzRhagqYjB1K3eBoQ9cEkv9
 ZDl4buQSUIRnR+Bko5kg1t0XOyBzSFRHx8slgZNKwFVOHbLm78Gj0nvgjQqSHc/r
 S1vqZdPDk9zL0fIg9PoLYiVDFUO9RcT6ueaI1tbyWXRVAxvxdH/A2mfE+RwTufvR
 tDNV3IG53+JGayTu4f4tnQZxMzt4lVk9DR829+JIGkcGAHHURWXJmqwCbwnvJSVv
 /iLLzYxtBN0mFDmhIYDgIuJWiz9y7pFVXuUu82RzqzxzBFe0XgLhG3e23G0WzAmT
 DAUbXoXhZcEOdj3Cj5Dl//RAtWtv8v6o2VHcDLtUkIrwuCc2jgcrzEdQZbxxMbav
 rlksaV8=
 =wefJ
 -----END PGP SIGNATURE-----

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

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes. It became a bit larger than wished, but
  all of them are device-specific small fixes, and it should be still
  fairly safe to take at the last minute.

  Included are a few quirks and fixes for Intel, AMD, HD-audio, and
  USB-audio, as well as a race fix in aloop driver and corrections of
  Cirrus firmware kunit test"

* tag 'sound-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda/realtek: Enable headset mic for Acer Nitro 5
  ASoC: fsl_xcvr: fix missing lock in fsl_xcvr_mode_put()
  ASoC: dt-bindings: ti,tlv320aic3x: Add compatible string ti,tlv320aic23
  ASoC: amd: fix memory leak in acp3x pdm dma ops
  ALSA: usb-audio: fix broken logic in snd_audigy2nx_led_update()
  ALSA: aloop: Fix racy access at PCM trigger
  ASoC: rt1320: fix intermittent no-sound issue
  ASoC: SOF: Intel: use hdev->info.link_mask directly
  firmware: cs_dsp: rate-limit log messages in KUnit builds
  ASoC: amd: yc: Add quirk for HP 200 G2a 16
  ASoC: cs42l43: Correct handling of 3-pole jack load detection
  ASoC: Intel: sof_es8336: Add DMI quirk for Huawei BOD-WXX9
  ASoC: sof_sdw: Add a quirk for Lenovo laptop using sidecar amps with cs42l43
master
Linus Torvalds 2026-02-06 09:59:40 -08:00
commit 8770bd8f91
18 changed files with 234 additions and 56 deletions

View File

@ -46,6 +46,7 @@ maintainers:
properties:
compatible:
enum:
- ti,tlv320aic23
- ti,tlv320aic3x
- ti,tlv320aic33
- ti,tlv320aic3007

View File

@ -9,6 +9,7 @@
* Cirrus Logic International Semiconductor Ltd.
*/
#include <kunit/visibility.h>
#include <linux/cleanup.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
@ -24,6 +25,41 @@
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
#include "cs_dsp.h"
/*
* When the KUnit test is running the error-case tests will cause a lot
* of messages. Rate-limit to prevent overflowing the kernel log buffer
* during KUnit test runs.
*/
#if IS_ENABLED(CONFIG_FW_CS_DSP_KUNIT_TEST)
bool cs_dsp_suppress_err_messages;
EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_err_messages);
bool cs_dsp_suppress_warn_messages;
EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_warn_messages);
bool cs_dsp_suppress_info_messages;
EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_info_messages);
#define cs_dsp_err(_dsp, fmt, ...) \
do { \
if (!cs_dsp_suppress_err_messages) \
dev_err_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
} while (false)
#define cs_dsp_warn(_dsp, fmt, ...) \
do { \
if (!cs_dsp_suppress_warn_messages) \
dev_warn_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
} while (false)
#define cs_dsp_info(_dsp, fmt, ...) \
do { \
if (!cs_dsp_suppress_info_messages) \
dev_info_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
} while (false)
#define cs_dsp_dbg(_dsp, fmt, ...) \
dev_dbg_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#else
#define cs_dsp_err(_dsp, fmt, ...) \
dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#define cs_dsp_warn(_dsp, fmt, ...) \
@ -32,6 +68,7 @@
dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#define cs_dsp_dbg(_dsp, fmt, ...) \
dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
#endif
#define ADSP1_CONTROL_1 0x00
#define ADSP1_CONTROL_2 0x02

View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* cs_dsp.h -- Private header for cs_dsp driver.
*
* Copyright (C) 2026 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef FW_CS_DSP_H
#define FW_CS_DSP_H
#if IS_ENABLED(CONFIG_KUNIT)
extern bool cs_dsp_suppress_err_messages;
extern bool cs_dsp_suppress_warn_messages;
extern bool cs_dsp_suppress_info_messages;
#endif
#endif /* ifndef FW_CS_DSP_H */

View File

@ -17,6 +17,8 @@
#include <linux/random.h>
#include <linux/regmap.h>
#include "../cs_dsp.h"
/*
* Test method is:
*
@ -2224,7 +2226,22 @@ static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp)
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
if (ret)
return ret;
/*
* The large number of test cases will cause an unusually large amount
* of dev_info() messages from cs_dsp, so suppress these.
*/
cs_dsp_suppress_info_messages = true;
return 0;
}
static void cs_dsp_bin_test_exit(struct kunit *test)
{
cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_bin_test_halo_init(struct kunit *test)
@ -2536,18 +2553,21 @@ static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {
static struct kunit_suite cs_dsp_bin_test_halo = {
.name = "cs_dsp_bin_halo",
.init = cs_dsp_bin_test_halo_init,
.exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_halo,
};
static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {
.name = "cs_dsp_bin_adsp2_32bit",
.init = cs_dsp_bin_test_adsp2_32bit_init,
.exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {
.name = "cs_dsp_bin_adsp2_16bit",
.init = cs_dsp_bin_test_adsp2_16bit_init,
.exit = cs_dsp_bin_test_exit,
.test_cases = cs_dsp_bin_test_cases_adsp2,
};

View File

@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include "../cs_dsp.h"
KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
@ -380,11 +382,9 @@ static void bin_block_payload_len_garbage(struct kunit *test)
static void cs_dsp_bin_err_test_exit(struct kunit *test)
{
/*
* Testing error conditions can produce a lot of log output
* from cs_dsp error messages, so rate limit the test cases.
*/
usleep_range(200, 500);
cs_dsp_suppress_err_messages = false;
cs_dsp_suppress_warn_messages = false;
cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@ -474,7 +474,19 @@ static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *ds
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
if (ret)
return ret;
/*
* Testing error conditions can produce a lot of log output
* from cs_dsp error messages, so suppress messages.
*/
cs_dsp_suppress_err_messages = true;
cs_dsp_suppress_warn_messages = true;
cs_dsp_suppress_info_messages = true;
return 0;
}
static int cs_dsp_bin_err_test_halo_init(struct kunit *test)

View File

@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include "../cs_dsp.h"
/*
* Test method is:
*
@ -1853,7 +1855,22 @@ static int cs_dsp_wmfw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
if (ret)
return ret;
/*
* The large number of test cases will cause an unusually large amount
* of dev_info() messages from cs_dsp, so suppress these.
*/
cs_dsp_suppress_info_messages = true;
return 0;
}
static void cs_dsp_wmfw_test_exit(struct kunit *test)
{
cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_wmfw_test_halo_init(struct kunit *test)
@ -2163,42 +2180,49 @@ static struct kunit_case cs_dsp_wmfw_test_cases_adsp2[] = {
static struct kunit_suite cs_dsp_wmfw_test_halo = {
.name = "cs_dsp_wmfwV3_halo",
.init = cs_dsp_wmfw_test_halo_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_halo,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw0 = {
.name = "cs_dsp_wmfwV0_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw1 = {
.name = "cs_dsp_wmfwV1_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw2 = {
.name = "cs_dsp_wmfwV2_adsp2_32bit",
.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw0 = {
.name = "cs_dsp_wmfwV0_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw1 = {
.name = "cs_dsp_wmfwV1_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};
static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw2 = {
.name = "cs_dsp_wmfwV2_adsp2_16bit",
.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init,
.exit = cs_dsp_wmfw_test_exit,
.test_cases = cs_dsp_wmfw_test_cases_adsp2,
};

View File

@ -18,6 +18,8 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include "../cs_dsp.h"
KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
@ -989,11 +991,9 @@ static void wmfw_v2_coeff_description_exceeds_block(struct kunit *test)
static void cs_dsp_wmfw_err_test_exit(struct kunit *test)
{
/*
* Testing error conditions can produce a lot of log output
* from cs_dsp error messages, so rate limit the test cases.
*/
usleep_range(200, 500);
cs_dsp_suppress_err_messages = false;
cs_dsp_suppress_warn_messages = false;
cs_dsp_suppress_info_messages = false;
}
static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@ -1072,7 +1072,19 @@ static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *d
return ret;
/* Automatically call cs_dsp_remove() when test case ends */
return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
if (ret)
return ret;
/*
* Testing error conditions can produce a lot of log output
* from cs_dsp error messages, so suppress messages.
*/
cs_dsp_suppress_err_messages = true;
cs_dsp_suppress_warn_messages = true;
cs_dsp_suppress_info_messages = true;
return 0;
}
static int cs_dsp_wmfw_err_test_halo_init(struct kunit *test)

View File

@ -12,3 +12,4 @@ MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("FW_CS_DSP");
MODULE_IMPORT_NS("FW_CS_DSP_KUNIT_TEST_UTILS");
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");

View File

@ -336,37 +336,43 @@ static bool is_access_interleaved(snd_pcm_access_t access)
static int loopback_check_format(struct loopback_cable *cable, int stream)
{
struct loopback_pcm *dpcm_play, *dpcm_capt;
struct snd_pcm_runtime *runtime, *cruntime;
struct loopback_setup *setup;
struct snd_card *card;
bool stop_capture = false;
int check;
if (cable->valid != CABLE_VALID_BOTH) {
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
goto __notify;
return 0;
}
runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
substream->runtime;
cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
substream->runtime;
check = runtime->format != cruntime->format ||
runtime->rate != cruntime->rate ||
runtime->channels != cruntime->channels ||
is_access_interleaved(runtime->access) !=
is_access_interleaved(cruntime->access);
if (!check)
return 0;
if (stream == SNDRV_PCM_STREAM_CAPTURE) {
return -EIO;
} else {
snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
substream, SNDRV_PCM_STATE_DRAINING);
__notify:
runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
substream->runtime;
setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
scoped_guard(spinlock_irqsave, &cable->lock) {
dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
if (cable->valid != CABLE_VALID_BOTH) {
if (stream == SNDRV_PCM_STREAM_CAPTURE || !dpcm_play)
return 0;
} else {
if (!dpcm_play || !dpcm_capt)
return -EIO;
runtime = dpcm_play->substream->runtime;
cruntime = dpcm_capt->substream->runtime;
if (!runtime || !cruntime)
return -EIO;
check = runtime->format != cruntime->format ||
runtime->rate != cruntime->rate ||
runtime->channels != cruntime->channels ||
is_access_interleaved(runtime->access) !=
is_access_interleaved(cruntime->access);
if (!check)
return 0;
if (stream == SNDRV_PCM_STREAM_CAPTURE)
return -EIO;
else if (cruntime->state == SNDRV_PCM_STATE_RUNNING)
stop_capture = true;
}
setup = get_setup(dpcm_play);
card = dpcm_play->loopback->card;
runtime = dpcm_play->substream->runtime;
if (setup->format != runtime->format) {
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&setup->format_id);
@ -389,6 +395,10 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
setup->access = runtime->access;
}
}
if (stop_capture)
snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
return 0;
}

View File

@ -6353,6 +6353,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),

View File

@ -301,9 +301,11 @@ static int acp_pdm_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct pdm_dev_data *adata = dev_get_drvdata(component->dev);
struct pdm_stream_instance *rtd = substream->runtime->private_data;
disable_pdm_interrupts(adata->acp_base);
adata->capture_stream = NULL;
kfree(rtd);
return 0;
}

View File

@ -640,6 +640,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "8BD6"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8EE4"),
}
},
{
.driver_data = &acp6x_card,
.matches = {

View File

@ -496,7 +496,23 @@ void cs42l43_bias_sense_timeout(struct work_struct *work)
pm_runtime_put_autosuspend(priv->dev);
}
static void cs42l43_start_load_detect(struct cs42l43_codec *priv)
static const struct reg_sequence cs42l43_3pole_patch[] = {
{ 0x4000, 0x00000055 },
{ 0x4000, 0x000000AA },
{ 0x17420, 0x8500F300 },
{ 0x17424, 0x36003E00 },
{ 0x4000, 0x00000000 },
};
static const struct reg_sequence cs42l43_4pole_patch[] = {
{ 0x4000, 0x00000055 },
{ 0x4000, 0x000000AA },
{ 0x17420, 0x7800E600 },
{ 0x17424, 0x36003800 },
{ 0x4000, 0x00000000 },
};
static void cs42l43_start_load_detect(struct cs42l43_codec *priv, bool mic)
{
struct cs42l43 *cs42l43 = priv->core;
@ -520,6 +536,15 @@ static void cs42l43_start_load_detect(struct cs42l43_codec *priv)
dev_err(priv->dev, "Load detect HP power down timed out\n");
}
if (mic)
regmap_multi_reg_write_bypassed(cs42l43->regmap,
cs42l43_4pole_patch,
ARRAY_SIZE(cs42l43_4pole_patch));
else
regmap_multi_reg_write_bypassed(cs42l43->regmap,
cs42l43_3pole_patch,
ARRAY_SIZE(cs42l43_3pole_patch));
regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3,
CS42L43_ADC1_EN_MASK | CS42L43_ADC2_EN_MASK, 0);
regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, CS42L43_HP_HPF_EN_MASK, 0);
@ -598,7 +623,7 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic)
reinit_completion(&priv->load_detect);
cs42l43_start_load_detect(priv);
cs42l43_start_load_detect(priv, mic);
time_left = wait_for_completion_timeout(&priv->load_detect,
msecs_to_jiffies(CS42L43_LOAD_TIMEOUT_MS));
cs42l43_stop_load_detect(priv);
@ -622,11 +647,11 @@ static int cs42l43_run_load_detect(struct cs42l43_codec *priv, bool mic)
}
switch (val & CS42L43_AMP3_RES_DET_MASK) {
case 0x0: // low impedance
case 0x1: // high impedance
case 0x0: // < 22 Ohm impedance
case 0x1: // < 150 Ohm impedance
case 0x2: // < 1000 Ohm impedance
return CS42L43_JACK_HEADPHONE;
case 0x2: // lineout
case 0x3: // Open circuit
case 0x3: // > 1000 Ohm impedance
return CS42L43_JACK_LINEOUT;
default:
return -EINVAL;

View File

@ -203,6 +203,7 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0x3fc2bfc2, 0x00 },
{ 0x3fc2bfc1, 0x00 },
{ 0x3fc2bfc0, 0x07 },
{ 0x1000cc46, 0x00 },
{ 0x0000d486, 0x43 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x00 },
{ 0x1000db00, 0x07 },
@ -354,6 +355,7 @@ static const struct reg_sequence rt1321_blind_write[] = {
{ 0x0000d73d, 0xd7 },
{ 0x0000d73e, 0x00 },
{ 0x0000d73f, 0x10 },
{ 0x1000cd56, 0x00 },
{ 0x3fc2dfc3, 0x00 },
{ 0x3fc2dfc2, 0x00 },
{ 0x3fc2dfc1, 0x00 },

View File

@ -223,10 +223,13 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol,
xcvr->mode = snd_soc_enum_item_to_val(e, item[0]);
down_read(&card->snd_card->controls_rwsem);
fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
(xcvr->mode == FSL_XCVR_MODE_ARC));
fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
(xcvr->mode == FSL_XCVR_MODE_EARC));
up_read(&card->snd_card->controls_rwsem);
/* Allow playback for SPDIF only */
rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =

View File

@ -334,6 +334,15 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
* if the topology file is modified as well.
*/
static const struct dmi_system_id sof_es8336_quirk_table[] = {
{
.callback = sof_es8336_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"),
DMI_MATCH(DMI_PRODUCT_NAME, "BOD-WXX9"),
},
.driver_data = (void *)(SOF_ES8336_HEADPHONE_GPIO |
SOF_ES8336_ENABLE_DMIC)
},
{
.callback = sof_es8336_quirk_cb,
.matches = {

View File

@ -1304,9 +1304,8 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
int i;
hdev = pdata->hw_pdata;
link_mask = hdev->info.link_mask;
if (!link_mask) {
if (!hdev->info.link_mask) {
dev_info(sdev->dev, "SoundWire links not enabled\n");
return NULL;
}
@ -1337,7 +1336,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
* link_mask supported by hw and then go on searching
* link_adr
*/
if (~link_mask & mach->link_mask)
if (~hdev->info.link_mask & mach->link_mask)
continue;
/* No need to match adr if there is no links defined */

View File

@ -311,13 +311,8 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer,
if (pm.err < 0)
return pm.err;
if (chip->usb_id == USB_ID(0x041e, 0x3042))
err = snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
!value, 0, NULL, 0);
/* USB X-Fi S51 Pro */
if (chip->usb_id == USB_ID(0x041e, 0x30df))
if (chip->usb_id == USB_ID(0x041e, 0x3042) || /* USB X-Fi S51 */
chip->usb_id == USB_ID(0x041e, 0x30df)) /* USB X-Fi S51 Pro */
err = snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,