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
commit
19cbc75c56
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue