sound fixes for 7.1-rc3

Again a collection of small fixes, mostly for device-specific ones.
 The only big LOC is about the removal of pretty old dead code in
 ab8500 codec driver, while the rest all nice small changes.
 
 * Core / API:
 - Fix race in deferred fasync state checks
 - Fix UMP group filtering in sequencer
 
 * ASoC:
 - cs35l56: fixes for driver cleanup and error paths
 - tas2764/2770: workaround for bogus temperature readings
 - wm_adsp: fixes for firmware unit tests
 - amd-yc: more DMI quirks for laptops
 - Minor fixes for fsl_xcvr and spacemit
 
 * HD-Audio:
 - Mute LED and speaker quirks for HP, Lenovo, and Xiaomi laptops
 
 * USB-audio:
 - New device-specific quirks (Motu, JBL, AlphaTheta, Razer)
 - Fix of MIDI2 playback on resume
 
 * Others:
 - Firewire-tascam control event fix
 - Minor cleanups and fixes for sparc/dbri and pcmtest
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmn8aHoOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE/Q2w//RiWXbrpHnLH0s7mHF1M0/rvEIotEpv0IaqiN
 4vyjnH8wuBPY35xwX80yLZTjSHxsLc4JYybQx8EcS/sA59laoDaK8SjoaYNuVcNl
 3U09PHG4jJvhRrwMCljQtef/V3SHoTGmwXbvtyH7y+6R603EGwKXUI8GZclUrOAV
 +YMSMkGm2s07kndNWQUy5A8Wn+9gKr7wq5M6D2CmkOoYqkMNibMsJOvFcyCS+rRQ
 8KUVPLbL22M12M5JwBTcMagRsnZ9SNRgHSqN88WWjfKUQ8Hbbqvsq58LGY5hOwtM
 SMluSkhk8+SnAVBZ9bNc/sXeA5nZfGVDZLrl1rB/HbZWTOwjcsqGgA041p7WHaiP
 ue7DRci5bzToomxppH0sG2IEgelua4S/OUnnFXo8pDCaR0Xv3ZRoq1noDlX/rcPF
 Cej9reA1Xp0nYSHVBMsvfJlZdbeuQiDU0piaoV3ze+RDctLsuDD5HeDfgrg/q6YI
 AQdyPRMiRt9h88mi7/X8EzaWGlryfJgJcVOl9/qK9T39H2byFae7YRo2AiReHIs3
 1amTKMUu7EhSmgzCEv6yyz2YTbhn9M9wXRrS3F5C1m6/R2B0Q8hOsz26yAWAAiEO
 yNvN5Duj8auBEavZz+HrDLjWWS/V4WtZF7vBFo3AZLrMnq9CyMqObUnf5kzvkpVp
 iERsof0=
 =prTy
 -----END PGP SIGNATURE-----

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

Pull sound fixes from Takashi Iwai:
 "Again a collection of small fixes, mostly for device-specific ones.

  The only big LOC is about the removal of pretty old dead code in
  ab8500 codec driver, while the rest all nice small changes.

  Core / API:
   - Fix race in deferred fasync state checks
   - Fix UMP group filtering in sequencer

  ASoC:
   - cs35l56: fixes for driver cleanup and error paths
   - tas2764/2770: workaround for bogus temperature readings
   - wm_adsp: fixes for firmware unit tests
   - amd-yc: more DMI quirks for laptops
   - Minor fixes for fsl_xcvr and spacemit

  HD-Audio:
   - Mute LED and speaker quirks for HP, Lenovo, and Xiaomi laptops

  USB-audio:
   - New device-specific quirks (Motu, JBL, AlphaTheta, Razer)
   - Fix of MIDI2 playback on resume

  Others:
   - Firewire-tascam control event fix
   - Minor cleanups and fixes for sparc/dbri and pcmtest"

* tag 'sound-7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (28 commits)
  ASoC: cs35l56: Destroy workqueue in probe error path
  ASoC: cs35l56: Don't use devres to unregister component
  ALSA: sparc/dbri: add missing fallthrough
  ALSA: core: Serialize deferred fasync state checks
  ALSA: hda/realtek: Add mute LED fixup for HP Pavilion 15-cs1xxx
  ALSA: seq: Fix UMP group 16 filtering
  ASoC: wm_adsp_fw_find_test: Clear searched_fw_files in find-by-index test
  ASoC: wm_adsp_fw_find_test: Redirect wm_adsp_release_firmware_files()
  ASoC: tas2770: Deal with bogus initial temperature value
  ASoC: tas2764: Deal with bogus initial temperature register value
  ALSA: usb-audio: add clock quirk for Motu 1248
  ALSA: usb-audio: midi2: Restart output URBs on resume
  ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP Envy X360 15-fh0xxx
  ALSA: usb-audio: Add quirk flags for JBL Pebbles
  ALSA: firewire-tascam: Do not drop unread control events
  ALSA: usb-audio: Add quirk flags for AlphaTheta EUPHONIA
  ASoC: fsl_xcvr: Fix event generation for cached controls
  ASoC: sdw_utils: avoid the SDCA companion function not supported failure
  ASoC: amd: yc: Add HP OMEN Gaming Laptop 16-ap0xxx product line in quirk table
  ASoC: cs35l56: Fix out-of-bounds in dev_err() in cs35l56_read_onchip_spkid()
  ...
master
Linus Torvalds 2026-05-07 08:55:15 -07:00
commit 19cbc75c56
21 changed files with 243 additions and 353 deletions

View File

@ -148,9 +148,11 @@ EXPORT_SYMBOL_GPL(snd_fasync_helper);
void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll)
{
if (!fasync || !fasync->on)
if (!fasync)
return;
guard(spinlock_irqsave)(&snd_fasync_lock);
if (!fasync->on)
return;
fasync->signal = signal;
fasync->poll = poll;
list_move(&fasync->list, &snd_fasync_list);
@ -163,8 +165,10 @@ void snd_fasync_free(struct snd_fasync *fasync)
if (!fasync)
return;
scoped_guard(spinlock_irq, &snd_fasync_lock)
scoped_guard(spinlock_irq, &snd_fasync_lock) {
fasync->on = 0;
list_del_init(&fasync->list);
}
flush_work(&snd_fasync_work);
kfree(fasync);

View File

@ -1253,7 +1253,7 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3))
client->midi_version = client_info->midi_version;
memcpy(client->event_filter, client_info->event_filter, 32);
client->group_filter = client_info->group_filter;
client->group_filter = client_info->group_filter & SND_SEQ_GROUP_FILTER_MASK;
/* notify the change */
snd_seq_system_client_ev_client_change(client->number);

View File

@ -14,6 +14,9 @@
/* client manager */
#define SND_SEQ_GROUP_FILTER_MASK GENMASK(SNDRV_UMP_MAX_GROUPS, 0)
#define SND_SEQ_GROUP_FILTER_GROUPS GENMASK(SNDRV_UMP_MAX_GROUPS, 1)
struct snd_seq_user_client {
struct file *file; /* file struct of client */
/* ... */
@ -40,7 +43,7 @@ struct snd_seq_client {
int number; /* client number */
unsigned int filter; /* filter flags */
DECLARE_BITMAP(event_filter, 256);
unsigned short group_filter;
unsigned int group_filter;
snd_use_lock_t use_lock;
int event_lost;
/* ports */

View File

@ -369,7 +369,7 @@ static void setup_client_group_filter(struct seq_ump_client *client)
cptr = snd_seq_kernel_client_get(client->seq_client);
if (!cptr)
return;
filter = ~(1U << 0); /* always allow groupless messages */
filter = SND_SEQ_GROUP_FILTER_GROUPS; /* always allow groupless messages */
for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
if (client->ump->groups[p].active)
filter &= ~(1U << (p + 1));

View File

@ -679,9 +679,9 @@ static ssize_t pattern_read(struct file *file, char __user *u_buff, size_t len,
return 0;
if (copy_to_user(u_buff, patt_buf->buf + *off, to_read))
to_read = 0;
else
*off += to_read;
return -EFAULT;
*off += to_read;
return to_read;
}

View File

@ -73,6 +73,7 @@ static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf,
length = rounddown(remained, sizeof(*entries));
if (length == 0)
break;
tail_pos = head_pos + length / sizeof(*entries);
spin_unlock_irq(&tscm->lock);
if (copy_to_user(pos, &entries[head_pos], length))

View File

@ -1669,6 +1669,21 @@ static void alc295_fixup_hp_mute_led_coefbit11(struct hda_codec *codec,
}
}
/* Override wrong pin to NID 0x1b (F.32 BIOS reports 0x18 via DMI OEM string)
* on HP pavilion 15-cs1xxx laptops
*/
static void alc295_fixup_hp_pavilion_mute_led_1b(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
struct alc_spec *spec = codec->spec;
alc269_fixup_hp_mute_led(codec, fix, action);
if (action == HDA_FIXUP_ACT_PRE_PROBE)
spec->mute_led_nid = 0x1b;
}
static void alc233_fixup_lenovo_coef_micmute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -3390,6 +3405,19 @@ static void alc256_fixup_mic_no_presence_and_resume(struct hda_codec *codec,
}
}
static void alc256_fixup_xiaomi_pro15_resume(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
/*
* On the Xiaomi Mi Laptop Pro 15 (TM1905, SSID 1d72:1905) the ALC256
* codec sets coefficient 0x10 bit 9 to 1 after S3 resume, silencing
* the internal speaker. Bluetooth and HDMI audio are unaffected.
* Clear the bit so the speaker keeps working across suspend cycles.
*/
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
}
static void alc256_decrease_headphone_amp_val(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -3857,6 +3885,7 @@ enum {
ALC290_FIXUP_SUBWOOFER,
ALC290_FIXUP_SUBWOOFER_HSJACK,
ALC295_FIXUP_HP_MUTE_LED_COEFBIT11,
ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B,
ALC269_FIXUP_THINKPAD_ACPI,
ALC269_FIXUP_LENOVO_XPAD_ACPI,
ALC269_FIXUP_DMIC_THINKPAD_ACPI,
@ -4052,6 +4081,7 @@ enum {
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
ALC233_FIXUP_NO_AUDIO_JACK,
ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME,
ALC256_FIXUP_XIAOMI_PRO15_RESUME,
ALC285_FIXUP_LEGION_Y9000X_SPEAKERS,
ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE,
ALC287_FIXUP_LEGION_16ACHG6,
@ -4123,6 +4153,7 @@ enum {
ALC245_FIXUP_CS35L41_I2C_2_MUTE_LED,
ALC236_FIXUP_HP_DMIC,
ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO,
ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@ -5700,6 +5731,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc295_fixup_hp_mute_led_coefbit11,
},
[ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc295_fixup_hp_pavilion_mute_led_1b,
},
[ALC298_FIXUP_SAMSUNG_AMP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_samsung_amp,
@ -6240,6 +6275,10 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
},
[ALC256_FIXUP_XIAOMI_PRO15_RESUME] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc256_fixup_xiaomi_pro15_resume,
},
[ALC287_FIXUP_LEGION_16ACHG6] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_legion_16achg6_speakers,
@ -6675,6 +6714,12 @@ static const struct hda_fixup alc269_fixups[] = {
{ 0x1b, 0x90170110 },
{ }
}
},
[ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l41_fixup_i2c_two,
.chained = true,
.chain_id = ALC245_FIXUP_HP_X360_MUTE_LEDS
}
};
@ -6906,6 +6951,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x856a, "HP Pavilion 15-cs1xxx", ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B),
SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
SND_PCI_QUIRK(0x103c, 0x8603, "HP Omen 17-cb0xxx", ALC285_FIXUP_HP_MUTE_LED),
@ -7097,7 +7143,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8be6, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8be7, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8be8, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy x360 2-in-1 Laptop 15-fh0xxx", ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX),
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX),
@ -7629,6 +7675,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3801, "Lenovo Yoga9 14IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
HDA_CODEC_QUIRK(0x17aa, 0x3802, "DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8", ALC287_FIXUP_TAS2781_I2C),
/* Yoga Pro 9 16IMH9 shares PCI SSID 17aa:3811 with Legion S7 15IMH05;
* use codec SSID to distinguish them
*/
HDA_CODEC_QUIRK(0x17aa, 0x38d6, "Lenovo Yoga Pro 9 16IMH9", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3811, "Legion S7 15IMH05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
@ -7774,6 +7824,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1905, "Xiaomi Mi Laptop Pro 15", ALC256_FIXUP_XIAOMI_PRO15_RESUME),
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(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),

View File

@ -59,6 +59,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15-fc0xxx"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Gaming Laptop 16-ap0xxx"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
@ -479,6 +486,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7VE"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
@ -668,6 +682,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "8EE4"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8E35"),
}
},
{
.driver_data = &acp6x_card,
.matches = {

View File

@ -60,19 +60,6 @@
low before proceeding with the configuration sequence */
#define AB8500_ANC_SM_DELAY 2000
#define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = filter_control_info, \
.get = filter_control_get, .put = filter_control_put, \
.private_value = (unsigned long)&(struct filter_control) \
{.count = xcount, .min = xmin, .max = xmax} }
struct filter_control {
long min, max;
unsigned int count;
long value[128];
};
/* Sidetone states */
static const char * const enum_sid_state[] = {
"Unconfigured",
@ -85,45 +72,13 @@ enum sid_state {
SID_FIR_CONFIGURED = 2,
};
static const char * const enum_anc_state[] = {
"Unconfigured",
"Apply FIR and IIR",
"FIR and IIR are configured",
"Apply FIR",
"FIR is configured",
"Apply IIR",
"IIR is configured"
};
enum anc_state {
ANC_UNCONFIGURED = 0,
ANC_APPLY_FIR_IIR = 1,
ANC_FIR_IIR_CONFIGURED = 2,
ANC_APPLY_FIR = 3,
ANC_FIR_CONFIGURED = 4,
ANC_APPLY_IIR = 5,
ANC_IIR_CONFIGURED = 6
};
/* Analog microphones */
enum amic_idx {
AMIC_IDX_1A,
AMIC_IDX_1B,
AMIC_IDX_2
};
/* Private data for AB8500 device-driver */
struct ab8500_codec_drvdata {
struct regmap *regmap;
struct mutex ctrl_lock;
/* Sidetone */
long *sid_fir_values;
enum sid_state sid_status;
/* ANC */
long *anc_fir_values;
long *anc_iir_values;
enum anc_state anc_status;
};
static inline const char *amic_micbias_str(enum amic_micbias micbias)
@ -1024,89 +979,6 @@ static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = {
{"MIC2 V-AMICx Enable", NULL, "V-AMIC2"},
};
/* ANC FIR-coefficients configuration sequence */
static void anc_fir(struct snd_soc_component *component,
unsigned int bnk, unsigned int par, unsigned int val)
{
if (par == 0 && bnk == 0)
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCFIRUPDATE),
BIT(AB8500_ANCCONF1_ANCFIRUPDATE));
snd_soc_component_write(component, AB8500_ANCCONF5, val >> 8 & 0xff);
snd_soc_component_write(component, AB8500_ANCCONF6, val & 0xff);
if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1)
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0);
}
/* ANC IIR-coefficients configuration sequence */
static void anc_iir(struct snd_soc_component *component, unsigned int bnk,
unsigned int par, unsigned int val)
{
if (par == 0) {
if (bnk == 0) {
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCIIRINIT),
BIT(AB8500_ANCCONF1_ANCIIRINIT));
usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY*2);
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCIIRINIT), 0);
usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY*2);
} else {
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCIIRUPDATE),
BIT(AB8500_ANCCONF1_ANCIIRUPDATE));
}
} else if (par > 3) {
snd_soc_component_write(component, AB8500_ANCCONF7, 0);
snd_soc_component_write(component, AB8500_ANCCONF8, val >> 16 & 0xff);
}
snd_soc_component_write(component, AB8500_ANCCONF7, val >> 8 & 0xff);
snd_soc_component_write(component, AB8500_ANCCONF8, val & 0xff);
if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1)
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0);
}
/* ANC IIR-/FIR-coefficients configuration sequence */
static void anc_configure(struct snd_soc_component *component,
bool apply_fir, bool apply_iir)
{
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(component->dev);
unsigned int bnk, par, val;
dev_dbg(component->dev, "%s: Enter.\n", __func__);
if (apply_fir)
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ENANC), 0);
snd_soc_component_update_bits(component, AB8500_ANCCONF1,
BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC));
if (apply_fir)
for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) {
val = snd_soc_component_read(component,
drvdata->anc_fir_values[par]);
anc_fir(component, bnk, par, val);
}
if (apply_iir)
for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) {
val = snd_soc_component_read(component,
drvdata->anc_iir_values[par]);
anc_iir(component, bnk, par, val);
}
dev_dbg(component->dev, "%s: Exit.\n", __func__);
}
/*
* Control-events
*/
@ -1130,7 +1002,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(component->dev);
unsigned int param, sidconf, val;
unsigned int param, sidconf;
int status = 1;
dev_dbg(component->dev, "%s: Enter\n", __func__);
@ -1159,9 +1031,8 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol,
snd_soc_component_write(component, AB8500_SIDFIRADR, 0);
for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) {
val = snd_soc_component_read(component, drvdata->sid_fir_values[param]);
snd_soc_component_write(component, AB8500_SIDFIRCOEF1, val >> 8 & 0xff);
snd_soc_component_write(component, AB8500_SIDFIRCOEF2, val & 0xff);
snd_soc_component_write(component, AB8500_SIDFIRCOEF1, 0);
snd_soc_component_write(component, AB8500_SIDFIRCOEF2, 0);
}
snd_soc_component_update_bits(component, AB8500_SIDFIRADR,
@ -1180,136 +1051,6 @@ out:
return status;
}
static int anc_status_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(component->dev);
mutex_lock(&drvdata->ctrl_lock);
ucontrol->value.enumerated.item[0] = drvdata->anc_status;
mutex_unlock(&drvdata->ctrl_lock);
return 0;
}
static int anc_status_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(component->dev);
struct device *dev = component->dev;
bool apply_fir, apply_iir;
unsigned int req;
int status;
dev_dbg(dev, "%s: Enter.\n", __func__);
mutex_lock(&drvdata->ctrl_lock);
req = ucontrol->value.enumerated.item[0];
if (req >= ARRAY_SIZE(enum_anc_state)) {
status = -EINVAL;
goto cleanup;
}
if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR &&
req != ANC_APPLY_IIR) {
dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n",
__func__, enum_anc_state[req]);
status = -EINVAL;
goto cleanup;
}
apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR;
apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR;
status = snd_soc_dapm_force_enable_pin(dapm, "ANC Configure Input");
if (status < 0) {
dev_err(dev,
"%s: ERROR: Failed to enable power (status = %d)!\n",
__func__, status);
goto cleanup;
}
snd_soc_dapm_sync(dapm);
anc_configure(component, apply_fir, apply_iir);
if (apply_fir) {
if (drvdata->anc_status == ANC_IIR_CONFIGURED)
drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
drvdata->anc_status = ANC_FIR_CONFIGURED;
}
if (apply_iir) {
if (drvdata->anc_status == ANC_FIR_CONFIGURED)
drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
drvdata->anc_status = ANC_IIR_CONFIGURED;
}
status = snd_soc_dapm_disable_pin(dapm, "ANC Configure Input");
snd_soc_dapm_sync(dapm);
cleanup:
mutex_unlock(&drvdata->ctrl_lock);
if (status < 0)
dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n",
__func__, status);
dev_dbg(dev, "%s: Exit.\n", __func__);
return (status < 0) ? status : 1;
}
static int filter_control_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct filter_control *fc =
(struct filter_control *)kcontrol->private_value;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = fc->count;
uinfo->value.integer.min = fc->min;
uinfo->value.integer.max = fc->max;
return 0;
}
static int filter_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct ab8500_codec_drvdata *drvdata = snd_soc_component_get_drvdata(component);
struct filter_control *fc =
(struct filter_control *)kcontrol->private_value;
unsigned int i;
mutex_lock(&drvdata->ctrl_lock);
for (i = 0; i < fc->count; i++)
ucontrol->value.integer.value[i] = fc->value[i];
mutex_unlock(&drvdata->ctrl_lock);
return 0;
}
static int filter_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct ab8500_codec_drvdata *drvdata = snd_soc_component_get_drvdata(component);
struct filter_control *fc =
(struct filter_control *)kcontrol->private_value;
unsigned int i;
mutex_lock(&drvdata->ctrl_lock);
for (i = 0; i < fc->count; i++)
fc->value[i] = ucontrol->value.integer.value[i];
mutex_unlock(&drvdata->ctrl_lock);
return 0;
}
/*
* Controls - Non-DAPM ASoC
*/
@ -1597,7 +1338,6 @@ static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast,
static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state);
/* ANC */
static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state);
static struct snd_kcontrol_new ab8500_ctrls[] = {
/* Charge pump */
@ -1873,8 +1613,6 @@ static struct snd_kcontrol_new ab8500_ctrls[] = {
AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0),
/* ANC */
SOC_ENUM_EXT("ANC Status", soc_enum_ancstate,
anc_status_control_get, anc_status_control_put),
SOC_SINGLE_XR_SX("ANC Warp Delay Shift",
AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT,
AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0),
@ -1895,21 +1633,6 @@ static struct snd_kcontrol_new ab8500_ctrls[] = {
AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0),
};
static struct snd_kcontrol_new ab8500_filter_controls[] = {
AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS,
AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX),
AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS,
AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX),
AB8500_FILTER_CONTROL("Sidetone FIR Coefficients",
AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN,
AB8500_SID_FIR_COEFF_MAX)
};
enum ab8500_filter {
AB8500_FILTER_ANC_FIR = 0,
AB8500_FILTER_ANC_IIR = 1,
AB8500_FILTER_SID_FIR = 2,
};
/*
* Extended interface for codec-driver
*/
@ -2454,7 +2177,6 @@ static int ab8500_codec_probe(struct snd_soc_component *component)
struct device_node *np = dev->of_node;
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
struct ab8500_codec_platform_data codec_pdata;
struct filter_control *fc;
int status;
dev_dbg(dev, "%s: Enter.\n", __func__);
@ -2486,25 +2208,6 @@ static int ab8500_codec_probe(struct snd_soc_component *component)
snd_soc_component_write(component, AB8500_SHORTCIRCONF,
BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
/* Add filter controls */
status = snd_soc_add_component_controls(component, ab8500_filter_controls,
ARRAY_SIZE(ab8500_filter_controls));
if (status < 0) {
dev_err(dev,
"%s: failed to add ab8500 filter controls (%d).\n",
__func__, status);
return status;
}
fc = (struct filter_control *)
ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value;
drvdata->anc_fir_values = (long *)fc->value;
fc = (struct filter_control *)
ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value;
drvdata->anc_iir_values = (long *)fc->value;
fc = (struct filter_control *)
ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value;
drvdata->sid_fir_values = (long *)fc->value;
snd_soc_dapm_disable_pin(dapm, "ANC Configure Input");
mutex_init(&drvdata->ctrl_lock);
@ -2538,7 +2241,6 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
if (!drvdata)
return -ENOMEM;
drvdata->sid_status = SID_UNCONFIGURED;
drvdata->anc_status = ANC_UNCONFIGURED;
dev_set_drvdata(&pdev->dev, drvdata);
drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev,

View File

@ -851,9 +851,11 @@ out_sync:
err:
regcache_cache_only(cs35l56_base->regmap, true);
regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
cs35l56_hibernate_seq,
ARRAY_SIZE(cs35l56_hibernate_seq));
if (cs35l56_base->can_hibernate) {
regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
cs35l56_hibernate_seq,
ARRAY_SIZE(cs35l56_hibernate_seq));
}
return ret;
}
@ -1728,8 +1730,7 @@ int cs35l56_read_onchip_spkid(struct cs35l56_base *cs35l56_base)
ret = regmap_read(regmap, CS35L56_GPIO_STATUS1, &val);
if (ret) {
dev_err(cs35l56_base->dev, "GPIO%d status read failed: %d\n",
cs35l56_base->onchip_spkid_gpios[i] + 1, ret);
dev_err(cs35l56_base->dev, "GPIO status read failed: %d\n", ret);
return ret;
}

View File

@ -1956,9 +1956,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
goto err;
}
ret = devm_snd_soc_register_component(cs35l56->base.dev,
&soc_component_dev_cs35l56,
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
ret = snd_soc_register_component(cs35l56->base.dev,
&soc_component_dev_cs35l56,
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
if (ret < 0) {
dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
goto err;
@ -1970,6 +1970,9 @@ err:
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
if (cs35l56->dsp_wq)
destroy_workqueue(cs35l56->dsp_wq);
return ret;
}
EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, "SND_SOC_CS35L56_CORE");
@ -2057,6 +2060,8 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, "SND_SOC_CS35L56_CORE");
void cs35l56_remove(struct cs35l56_private *cs35l56)
{
snd_soc_unregister_component(cs35l56->base.dev);
cs35l56->base.init_done = false;
/*

View File

@ -684,18 +684,33 @@ static int tas2764_read_die_temp(struct tas2764_priv *tas2764, long *result)
* As per datasheet, subtract 93 from raw value to get degrees
* Celsius. hwmon wants millidegrees.
*
* NOTE: The chip will initialise the TAS2764_TEMP register to
* 2.6 *C to avoid triggering temperature protection. Since the
* ADC is powered down during software shutdown, this value will
* persist until the chip is fully powered up (e.g. the PCM it's
* attached to is opened). The ADC will power down again when
* the chip is put back into software shutdown, with the last
* value sampled persisting in the ADC's register.
* NOTE: The TAS2764 datasheet mentions initialising TAS2764_TEMP
* such that the temperature is 2.6 *C, however the register
* is actually initialised to 0. The ADC is also powered down during
* software shutdown. The last sampled temperature will persist
* in the register while the amp is in this power state.
*/
if (reg == 0)
return -ENODATA;
*result = (reg - 93) * 1000;
return 0;
}
static int tas2764_hwmon_is_fault(struct tas2764_priv *tas2764, long *result)
{
int ret;
long temp;
ret = tas2764_read_die_temp(tas2764, &temp);
if (ret == -ENODATA) {
*result = true;
return 0;
}
return ret;
}
static umode_t tas2764_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type, u32 attr,
int channel)
@ -705,6 +720,7 @@ static umode_t tas2764_hwmon_is_visible(const void *data,
switch (attr) {
case hwmon_temp_input:
case hwmon_temp_fault:
return 0444;
default:
break;
@ -724,6 +740,9 @@ static int tas2764_hwmon_read(struct device *dev,
case hwmon_temp_input:
ret = tas2764_read_die_temp(tas2764, val);
break;
case hwmon_temp_fault:
ret = tas2764_hwmon_is_fault(tas2764, val);
break;
default:
ret = -EOPNOTSUPP;
break;
@ -733,7 +752,7 @@ static int tas2764_hwmon_read(struct device *dev,
}
static const struct hwmon_channel_info *const tas2764_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_FAULT),
NULL
};

View File

@ -633,10 +633,27 @@ static int tas2770_read_die_temp(struct tas2770_priv *tas2770, long *result)
* value read back from its registers will be the last value sampled
* before entering software shutdown.
*/
if (reading == 0)
return -ENODATA;
*result = (reading - (93 * 16)) * 1000 / 16;
return 0;
}
static int tas2770_hwmon_is_fault(struct tas2770_priv *tas2770, long *result)
{
int ret;
long temp;
ret = tas2770_read_die_temp(tas2770, &temp);
if (ret == -ENODATA) {
*result = true;
return 0;
}
return ret;
}
static umode_t tas2770_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type, u32 attr,
int channel)
@ -646,6 +663,7 @@ static umode_t tas2770_hwmon_is_visible(const void *data,
switch (attr) {
case hwmon_temp_input:
case hwmon_temp_fault:
return 0444;
default:
break;
@ -665,6 +683,9 @@ static int tas2770_hwmon_read(struct device *dev,
case hwmon_temp_input:
ret = tas2770_read_die_temp(tas2770, val);
break;
case hwmon_temp_fault:
ret = tas2770_hwmon_is_fault(tas2770, val);
break;
default:
ret = -EOPNOTSUPP;
break;
@ -674,7 +695,7 @@ static int tas2770_hwmon_read(struct device *dev,
}
static const struct hwmon_channel_info *const tas2770_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_FAULT),
NULL
};

View File

@ -45,6 +45,34 @@ struct wm_adsp_fw_find_test_params {
/* Dummy struct firmware to return from wm_adsp_request_firmware_files */
static const struct firmware wm_adsp_find_test_dummy_firmware;
static void wm_adsp_fw_find_test_release_firmware_files_stub(struct wm_adsp_fw_files *fw)
{
/*
* fw->wmfw.firmware and fw->coeff.firmware allocated by this KUnit
* test are dummies not allocated by the real request_firmware() call
* so they must not be passed to release_firmware().
* This function replaces wm_adsp_release_firmware_files().
*/
if (!fw)
return;
kfree(fw->wmfw.filename);
kfree(fw->coeff.filename);
fw->wmfw.firmware = NULL;
fw->coeff.firmware = NULL;
fw->wmfw.filename = NULL;
fw->coeff.filename = NULL;
}
static void wm_adsp_free_found_fw(struct kunit *test)
{
struct wm_adsp_fw_find_test *priv = test->priv;
wm_adsp_fw_find_test_release_firmware_files_stub(&priv->found_fw);
}
/* Simple lookup of a filename in a list of names */
static int wm_adsp_fw_find_test_firmware_request_simple_stub(const struct firmware **firmware,
const char *filename,
@ -97,9 +125,14 @@ static void wm_adsp_fw_find_test_pick_file(struct kunit *test)
kunit_activate_static_stub(test,
wm_adsp_firmware_request,
wm_adsp_fw_find_test_firmware_request_simple_stub);
kunit_activate_static_stub(test,
wm_adsp_release_firmware_files,
wm_adsp_fw_find_test_release_firmware_files_stub);
ret = wm_adsp_request_firmware_files(dsp, &priv->found_fw);
kunit_deactivate_static_stub(test, wm_adsp_firmware_request);
kunit_deactivate_static_stub(test, wm_adsp_release_firmware_files);
KUNIT_EXPECT_EQ_MSG(test, ret,
(params->expect_wmfw || params->expect_bin) ? 0 : -ENOENT,
"%s\n", priv->searched_fw_files);
@ -173,10 +206,13 @@ static void wm_adsp_fw_find_test_search_order(struct kunit *test)
kunit_activate_static_stub(test,
wm_adsp_firmware_request,
wm_adsp_fw_find_test_firmware_request_stub);
kunit_activate_static_stub(test,
wm_adsp_release_firmware_files,
wm_adsp_fw_find_test_release_firmware_files_stub);
wm_adsp_request_firmware_files(dsp, &priv->found_fw);
kunit_deactivate_static_stub(test, wm_adsp_firmware_request);
kunit_deactivate_static_stub(test, wm_adsp_release_firmware_files);
KUNIT_EXPECT_STREQ(test, priv->searched_fw_files, params->expected_searches);
@ -201,6 +237,7 @@ static void wm_adsp_fw_find_test_find_firmware_byindex(struct kunit *test)
dsp->cs_dsp.name = "cs1234";
dsp->part = "dsp1";
for (dsp->fw = 0;; dsp->fw++) {
fw_name = wm_adsp_get_fwf_name_by_index(dsp->fw);
if (!fw_name)
@ -209,14 +246,22 @@ static void wm_adsp_fw_find_test_find_firmware_byindex(struct kunit *test)
kunit_activate_static_stub(test,
wm_adsp_firmware_request,
wm_adsp_fw_find_test_firmware_request_stub);
kunit_activate_static_stub(test,
wm_adsp_release_firmware_files,
wm_adsp_fw_find_test_release_firmware_files_stub);
wm_adsp_request_firmware_files(dsp, &priv->found_fw);
kunit_deactivate_static_stub(test, wm_adsp_firmware_request);
kunit_deactivate_static_stub(test, wm_adsp_release_firmware_files);
KUNIT_EXPECT_NOT_NULL_MSG(test,
strstr(priv->searched_fw_files, fw_name),
"fw#%d Did not find '%s' in '%s'\n",
dsp->fw, fw_name, priv->searched_fw_files);
wm_adsp_free_found_fw(test);
memset(priv->searched_fw_files, 0, sizeof(priv->searched_fw_files));
}
}
@ -255,15 +300,7 @@ static int wm_adsp_fw_find_test_case_init(struct kunit *test)
static void wm_adsp_fw_find_test_case_exit(struct kunit *test)
{
struct wm_adsp_fw_find_test *priv = test->priv;
/*
* priv->found_wmfw_firmware and priv->found_bin_firmware are
* dummies not allocated by the real request_firmware() call they
* must not be passed to release_firmware().
*/
kfree(priv->found_fw.wmfw.filename);
kfree(priv->found_fw.coeff.filename);
wm_adsp_free_found_fw(test);
}
static void wm_adsp_fw_find_test_param_desc(const struct wm_adsp_fw_find_test_params *param,

View File

@ -228,10 +228,14 @@ static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
int changed;
memcpy(xcvr->cap_ds, ucontrol->value.bytes.data, FSL_XCVR_CAPDS_SIZE);
changed = memcmp(xcvr->cap_ds, ucontrol->value.bytes.data,
sizeof(xcvr->cap_ds)) != 0;
memcpy(xcvr->cap_ds, ucontrol->value.bytes.data,
sizeof(xcvr->cap_ds));
return 0;
return changed;
}
static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = {
@ -1040,10 +1044,15 @@ static int fsl_xcvr_tx_cs_put(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
int changed;
memcpy(xcvr->tx_iec958.status, ucontrol->value.iec958.status, 24);
changed = memcmp(xcvr->tx_iec958.status,
ucontrol->value.iec958.status,
sizeof(xcvr->tx_iec958.status)) != 0;
memcpy(xcvr->tx_iec958.status, ucontrol->value.iec958.status,
sizeof(xcvr->tx_iec958.status));
return 0;
return changed;
}
static struct snd_kcontrol_new fsl_xcvr_rx_ctls[] = {

View File

@ -1608,6 +1608,7 @@ int asoc_sdw_get_dai_type(u32 type)
switch (type) {
case SDCA_FUNCTION_TYPE_SMART_AMP:
case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
case SDCA_FUNCTION_TYPE_COMPANION_AMP:
return SOC_SDW_DAI_TYPE_AMP;
case SDCA_FUNCTION_TYPE_SMART_MIC:
case SDCA_FUNCTION_TYPE_SIMPLE_MIC:

View File

@ -148,10 +148,6 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
u32 val;
int ret;
val = readl(i2s->base + SSCR);
if (val & SSCR_SSE)
return 0;
dma_data = &i2s->playback_dma_data;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@ -199,6 +195,9 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
}
val = readl(i2s->base + SSCR);
if (val & SSCR_SSE)
return 0;
val &= ~SSCR_DW_32BYTE;
val |= data_width;
writel(val, i2s->base + SSCR);

View File

@ -592,6 +592,7 @@ static __u32 reverse_bytes(__u32 b, int len)
fallthrough;
case 2:
b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1);
fallthrough;
case 1:
case 0:
break;

View File

@ -208,11 +208,18 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
}
/*
* MOTU MicroBook IIc
* Sample rate changes takes more than 2 seconds for this device. Clock
* validity request returns false during that period.
* Quirk for older MOTU AVB / hybrid interfaces
*
* These devices take more than 2 seconds to switch sample rate or
* clock source. During this period the clock validity request
* returns false, causing ALSA to fail prematurely.
*
* Affected models (all use vendor 0x07fd):
* - MicroBook IIc 0x0004
* - 1248, 624, 8A, UltraLite AVB, 8M, 16A, ... 0x0005
*/
if (chip->usb_id == USB_ID(0x07fd, 0x0004)) {
if (chip->usb_id == USB_ID(0x07fd, 0x0004) || /* MicroBook IIc */
chip->usb_id == USB_ID(0x07fd, 0x0005)) { /* 1248 / 624 / 8A / UltraLite AVB / ... */
count = 0;
while ((!ret) && (count < 50)) {

View File

@ -227,7 +227,7 @@ static void kill_midi_urbs(struct snd_usb_midi2_endpoint *ep, bool suspending)
if (!ep)
return;
if (suspending)
ep->suspended = ep->running;
atomic_set(&ep->suspended, atomic_read(&ep->running));
atomic_set(&ep->running, 0);
for (i = 0; i < ep->num_urbs; i++) {
if (!ep->urbs[i].urb)
@ -1188,10 +1188,11 @@ void snd_usb_midi_v2_suspend_all(struct snd_usb_audio *chip)
static void resume_midi2_endpoint(struct snd_usb_midi2_endpoint *ep)
{
ep->running = ep->suspended;
if (ep->direction == STR_IN)
atomic_set(&ep->running, atomic_read(&ep->suspended));
atomic_set(&ep->suspended, 0);
if (ep->direction == STR_IN || atomic_read(&ep->running))
submit_io_urbs(ep);
/* FIXME: does it all? */
}
void snd_usb_midi_v2_resume_all(struct snd_usb_audio *chip)

View File

@ -2277,6 +2277,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x05fc, 0x0231, /* JBL Pebbles */
QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL | QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL |
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x0624, 0x3d3f, /* AB13X USB Audio */
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
@ -2366,6 +2369,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x152a, 0x880a, /* NeuralDSP Quad Cortex */
0), /* Doesn't have the vendor quirk which would otherwise apply */
DEVICE_FLG(0x1532, 0x055e, /* Razer Nommo V2 X */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */
@ -2458,6 +2463,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2b73, 0x0047, /* AlphaTheta EUPHONIA */
QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2d95, 0x8011, /* VIVO USB-C HEADSET */
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */