diff options
author | Linus Torvalds | 2020-04-10 12:27:06 -0700 |
---|---|---|
committer | Linus Torvalds | 2020-04-10 12:27:06 -0700 |
commit | 4aafdf688360bacd4b48c87e9a3d0c208baf31c4 (patch) | |
tree | 70bb5a053afb737621e8c07c9120059cb127d040 | |
parent | 93f3321f650c5e700478ee8ed2e118d8255095cd (diff) | |
parent | ddd5609fe8b682fbe81f71b27561f14d3611d856 (diff) |
Merge tag 'sound-fix-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"A collection of small fixes gathered since the previous update.
ALSA core:
- Regression fix for OSS PCM emulation
ASoC:
- Trivial fixes in reg bit mask ops, DAPM, DPCM and topology
- Lots of fixes for Intel-based devices
- Minor fixes for AMD, STM32, Qualcomm, Realtek
Others:
- Fixes for the bugs in mixer handling in HD-audio and ice1724
drivers that were caught by the recent kctl validator
- New quirks for HD-audio and USB-audio
Also this contains a fix for EDD firmware fix, which slipped from
anyone's hands"
* tag 'sound-fix-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (35 commits)
ALSA: hda: Add driver blacklist
ALSA: usb-audio: Add mixer workaround for TRX40 and co
ALSA: hda/realtek - Add quirk for MSI GL63
ALSA: ice1724: Fix invalid access for enumerated ctl items
ALSA: hda: Fix potential access overflow in beep helper
ASoC: cs4270: pull reset GPIO low then high
ALSA: hda/realtek - Add HP new mute led supported for ALC236
ALSA: hda/realtek - Add supported new mute Led for HP
ASoC: rt5645: Add platform-data for Medion E1239T
ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN MPWIN895CL tablet
ASoC: stm32: sai: Add missing cleanup
ALSA: usb-audio: Add registration quirk for Kingston HyperX Cloud Alpha S
ASoC: Intel: atom: Fix uninitialized variable compiler warning
ASoC: Intel: atom: Check drv->lock is locked in sst_fill_and_send_cmd_unlocked
ASoC: Intel: atom: Take the drv->lock mutex before calling sst_send_slot_map()
ASoC: SOF: Turn "firmware boot complete" message into a dbg message
ALSA: usb-audio: Add Pioneer DJ DJM-250MK2 quirk
ALSA: pcm: oss: Fix regression by buffer overflow fix (again)
ALSA: pcm: oss: Fix regression by buffer overflow fix
edd: Use scnprintf() for avoiding potential buffer overflow
...
32 files changed, 329 insertions, 44 deletions
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml index efce847a3408..83f44f07ac3f 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml @@ -49,7 +49,7 @@ required: examples: - | #include <dt-bindings/gpio/gpio.h> - i2c@0 { + i2c { #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 29906e39ab4b..14d0970a7198 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -341,7 +341,7 @@ edd_show_legacy_max_cylinder(struct edd_device *edev, char *buf) if (!info || !buf) return -EINVAL; - p += snprintf(p, left, "%u\n", info->legacy_max_cylinder); + p += scnprintf(p, left, "%u\n", info->legacy_max_cylinder); return (p - buf); } @@ -356,7 +356,7 @@ edd_show_legacy_max_head(struct edd_device *edev, char *buf) if (!info || !buf) return -EINVAL; - p += snprintf(p, left, "%u\n", info->legacy_max_head); + p += scnprintf(p, left, "%u\n", info->legacy_max_head); return (p - buf); } @@ -371,7 +371,7 @@ edd_show_legacy_sectors_per_track(struct edd_device *edev, char *buf) if (!info || !buf) return -EINVAL; - p += snprintf(p, left, "%u\n", info->legacy_sectors_per_track); + p += scnprintf(p, left, "%u\n", info->legacy_sectors_per_track); return (p - buf); } diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 78bac995db15..d4825b82c7a3 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -351,7 +351,7 @@ struct snd_soc_dai { /* bit field */ unsigned int probed:1; - unsigned int started:1; + unsigned int started[SNDRV_PCM_STREAM_LAST + 1]; }; static inline struct snd_soc_pcm_stream * diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index fbda4ebf38b3..59d62f05658f 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -197,7 +197,8 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin) } static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug, - snd_pcm_sframes_t frames) + snd_pcm_sframes_t frames, + bool check_size) { struct snd_pcm_plugin *plugin, *plugin_next; @@ -209,7 +210,7 @@ static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug, if (frames < 0) return frames; } - if (frames > plugin->buf_frames) + if (check_size && frames > plugin->buf_frames) frames = plugin->buf_frames; plugin = plugin_next; } @@ -217,13 +218,14 @@ static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug, } static snd_pcm_sframes_t calc_src_frames(struct snd_pcm_substream *plug, - snd_pcm_sframes_t frames) + snd_pcm_sframes_t frames, + bool check_size) { struct snd_pcm_plugin *plugin, *plugin_prev; plugin = snd_pcm_plug_last(plug); while (plugin && frames > 0) { - if (frames > plugin->buf_frames) + if (check_size && frames > plugin->buf_frames) frames = plugin->buf_frames; plugin_prev = plugin->prev; if (plugin->src_frames) { @@ -242,9 +244,9 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p return -ENXIO; switch (snd_pcm_plug_stream(plug)) { case SNDRV_PCM_STREAM_PLAYBACK: - return calc_src_frames(plug, drv_frames); + return calc_src_frames(plug, drv_frames, false); case SNDRV_PCM_STREAM_CAPTURE: - return calc_dst_frames(plug, drv_frames); + return calc_dst_frames(plug, drv_frames, false); default: snd_BUG(); return -EINVAL; @@ -257,9 +259,9 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc return -ENXIO; switch (snd_pcm_plug_stream(plug)) { case SNDRV_PCM_STREAM_PLAYBACK: - return calc_dst_frames(plug, clt_frames); + return calc_dst_frames(plug, clt_frames, false); case SNDRV_PCM_STREAM_CAPTURE: - return calc_src_frames(plug, clt_frames); + return calc_src_frames(plug, clt_frames, false); default: snd_BUG(); return -EINVAL; @@ -622,7 +624,7 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st src_channels = dst_channels; plugin = next; } - return snd_pcm_plug_client_size(plug, frames); + return calc_src_frames(plug, frames, true); } snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size) @@ -632,7 +634,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str snd_pcm_sframes_t frames = size; int err; - frames = snd_pcm_plug_slave_size(plug, frames); + frames = calc_src_frames(plug, frames, true); if (frames < 0) return frames; diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index f5fd62ed4df5..841523f6b88d 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -290,8 +290,12 @@ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_beep *beep = codec->beep; + int chs = get_amp_channels(kcontrol); + if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) { - ucontrol->value.integer.value[0] = + if (chs & 1) + ucontrol->value.integer.value[0] = beep->enabled; + if (chs & 2) ucontrol->value.integer.value[1] = beep->enabled; return 0; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 92a042e34d3e..bd093593f8fb 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2076,6 +2076,17 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, #endif } +/* Blacklist for skipping the whole probe: + * some HD-audio PCI entries are exposed without any codecs, and such devices + * should be ignored from the beginning. + */ +static const struct snd_pci_quirk driver_blacklist[] = { + SND_PCI_QUIRK(0x1043, 0x874f, "ASUS ROG Zenith II / Strix", 0), + SND_PCI_QUIRK(0x1462, 0xcb59, "MSI TRX40 Creator", 0), + SND_PCI_QUIRK(0x1462, 0xcb60, "MSI TRX40", 0), + {} +}; + static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .pcm_mmap_prepare = pcm_mmap_prepare, @@ -2092,6 +2103,11 @@ static int azx_probe(struct pci_dev *pci, bool schedule_probe; int err; + if (snd_pci_quirk_lookup(pci, driver_blacklist)) { + dev_info(&pci->dev, "Skipping the blacklisted device\n"); + return -ENODEV; + } + if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f66a48154a57..de2826f90d34 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -86,6 +86,14 @@ struct alc_spec { unsigned int gpio_mute_led_mask; unsigned int gpio_mic_led_mask; + unsigned int mute_led_coef_idx; + unsigned int mute_led_coefbit_mask; + unsigned int mute_led_coefbit_on; + unsigned int mute_led_coefbit_off; + unsigned int mic_led_coef_idx; + unsigned int mic_led_coefbit_mask; + unsigned int mic_led_coefbit_on; + unsigned int mic_led_coefbit_off; hda_nid_t headset_mic_pin; hda_nid_t headphone_mic_pin; @@ -2447,6 +2455,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), @@ -4178,6 +4187,111 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, } } +/* update mute-LED according to the speaker mute state via COEF bit */ +static void alc_fixup_mute_led_coefbit_hook(void *private_data, int enabled) +{ + struct hda_codec *codec = private_data; + struct alc_spec *spec = codec->spec; + + if (spec->mute_led_polarity) + enabled = !enabled; + + /* temporarily power up/down for setting COEF bit */ + enabled ? alc_update_coef_idx(codec, spec->mute_led_coef_idx, + spec->mute_led_coefbit_mask, spec->mute_led_coefbit_off) : + alc_update_coef_idx(codec, spec->mute_led_coef_idx, + spec->mute_led_coefbit_mask, spec->mute_led_coefbit_on); +} + +static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mute_led_polarity = 0; + spec->mute_led_coef_idx = 0x0b; + spec->mute_led_coefbit_mask = 1<<3; + spec->mute_led_coefbit_on = 1<<3; + spec->mute_led_coefbit_off = 0; + spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook; + spec->gen.vmaster_mute_enum = 1; + } +} + +static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mute_led_polarity = 0; + spec->mute_led_coef_idx = 0x34; + spec->mute_led_coefbit_mask = 1<<5; + spec->mute_led_coefbit_on = 0; + spec->mute_led_coefbit_off = 1<<5; + spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook; + spec->gen.vmaster_mute_enum = 1; + } +} + +/* turn on/off mic-mute LED per capture hook by coef bit */ +static void alc_hp_cap_micmute_update(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + if (spec->gen.micmute_led.led_value) + alc_update_coef_idx(codec, spec->mic_led_coef_idx, + spec->mic_led_coefbit_mask, spec->mic_led_coefbit_on); + else + alc_update_coef_idx(codec, spec->mic_led_coef_idx, + spec->mic_led_coefbit_mask, spec->mic_led_coefbit_off); +} + +static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mic_led_coef_idx = 0x19; + spec->mic_led_coefbit_mask = 1<<13; + spec->mic_led_coefbit_on = 1<<13; + spec->mic_led_coefbit_off = 0; + snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update); + } +} + +static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mic_led_coef_idx = 0x35; + spec->mic_led_coefbit_mask = 3<<2; + spec->mic_led_coefbit_on = 2<<2; + spec->mic_led_coefbit_off = 1<<2; + snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update); + } +} + +static void alc285_fixup_hp_mute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc285_fixup_hp_mute_led_coefbit(codec, fix, action); + alc285_fixup_hp_coef_micmute_led(codec, fix, action); +} + +static void alc236_fixup_hp_mute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc236_fixup_hp_mute_led_coefbit(codec, fix, action); + alc236_fixup_hp_coef_micmute_led(codec, fix, action); +} + #if IS_REACHABLE(CONFIG_INPUT) static void gpio2_mic_hotkey_event(struct hda_codec *codec, struct hda_jack_callback *event) @@ -5964,6 +6078,8 @@ enum { ALC285_FIXUP_THINKPAD_HEADSET_JACK, ALC294_FIXUP_ASUS_HPE, ALC285_FIXUP_HP_GPIO_LED, + ALC285_FIXUP_HP_MUTE_LED, + ALC236_FIXUP_HP_MUTE_LED, }; static const struct hda_fixup alc269_fixups[] = { @@ -7089,6 +7205,14 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_hp_gpio_led, }, + [ALC285_FIXUP_HP_MUTE_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_mute_led, + }, + [ALC236_FIXUP_HP_MUTE_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc236_fixup_hp_mute_led, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7234,6 +7358,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -7325,6 +7451,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 91f83cef0e56..9aa12a67d370 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -536,7 +536,7 @@ static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = wm_get(ice, WM_ADC_MUX) & 0x1f; + ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f; mutex_unlock(&ice->gpio_mutex); return 0; } @@ -550,7 +550,7 @@ static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol, mutex_lock(&ice->gpio_mutex); oval = wm_get(ice, WM_ADC_MUX); - nval = (oval & 0xe0) | ucontrol->value.integer.value[0]; + nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0]; if (nval != oval) { wm_put(ice, WM_ADC_MUX, nval); change = 1; diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index 3a3c47e820ab..f160d35a6832 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -139,6 +139,7 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, rv_writel(adata->tdm_fmt, rtd->acp3x_base + frmt_reg); } val = rv_readl(rtd->acp3x_base + reg_val); + val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK; val = val | (rtd->xfer_resolution << 3); rv_writel(val, rtd->acp3x_base + reg_val); return 0; diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h index 21e7ac017f2b..03fe93913e12 100644 --- a/sound/soc/amd/raven/acp3x.h +++ b/sound/soc/amd/raven/acp3x.h @@ -76,6 +76,8 @@ #define ACP_POWERED_OFF 0x02 #define ACP_POWER_OFF_IN_PROGRESS 0x03 +#define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38 + struct acp3x_platform_info { u16 play_i2s_instance; u16 cap_i2s_instance; diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c index e46c390683e7..b7a1efc7406e 100644 --- a/sound/soc/bcm/bcm63xx-pcm-whistler.c +++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c @@ -181,7 +181,7 @@ bcm63xx_pcm_pointer(struct snd_soc_component *component, snd_pcm_uframes_t x; struct bcm63xx_runtime_data *prtd = substream->runtime->private_data; - if ((void *)prtd->dma_addr_next == NULL) + if (!prtd->dma_addr_next) prtd->dma_addr_next = substream->runtime->dma_addr; x = bytes_to_frames(substream->runtime, diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 5f25b9f872bd..8a02791e44ad 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -137,6 +137,9 @@ struct cs4270_private { /* power domain regulators */ struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; + + /* reset gpio */ + struct gpio_desc *reset_gpio; }; static const struct snd_soc_dapm_widget cs4270_dapm_widgets[] = { @@ -649,6 +652,22 @@ static const struct regmap_config cs4270_regmap = { }; /** + * cs4270_i2c_remove - deinitialize the I2C interface of the CS4270 + * @i2c_client: the I2C client object + * + * This function puts the chip into low power mode when the i2c device + * is removed. + */ +static int cs4270_i2c_remove(struct i2c_client *i2c_client) +{ + struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); + + gpiod_set_value_cansleep(cs4270->reset_gpio, 0); + + return 0; +} + +/** * cs4270_i2c_probe - initialize the I2C interface of the CS4270 * @i2c_client: the I2C client object * @id: the I2C device ID (ignored) @@ -660,7 +679,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct cs4270_private *cs4270; - struct gpio_desc *reset_gpiod; unsigned int val; int ret, i; @@ -679,10 +697,21 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, if (ret < 0) return ret; - reset_gpiod = devm_gpiod_get_optional(&i2c_client->dev, "reset", - GPIOD_OUT_HIGH); - if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER) - return -EPROBE_DEFER; + /* reset the device */ + cs4270->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(cs4270->reset_gpio)) { + dev_dbg(&i2c_client->dev, "Error getting CS4270 reset GPIO\n"); + return PTR_ERR(cs4270->reset_gpio); + } + + if (cs4270->reset_gpio) { + dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); + gpiod_set_value_cansleep(cs4270->reset_gpio, 1); + } + + /* Sleep 500ns before i2c communications */ + ndelay(500); cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap); if (IS_ERR(cs4270->regmap)) @@ -735,6 +764,7 @@ static struct i2c_driver cs4270_i2c_driver = { }, .id_table = cs4270_id, .probe = cs4270_i2c_probe, + .remove = cs4270_i2c_remove, }; module_i2c_driver(cs4270_i2c_driver); diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 92d67010aeed..6ba1849a77b0 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3758,6 +3758,14 @@ static const struct dmi_system_id dmi_platform_data[] = { }, .driver_data = (void *)&kahlee_platform_data, }, + { + .ident = "Medion E1239T", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E1239T MD60568"), + }, + .driver_data = (void *)&intel_braswell_platform_data, + }, { } }; diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index c9268a230daa..d36f560ad7a8 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -3703,7 +3703,7 @@ static const struct acpi_device_id rt5682_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); #endif -static struct i2c_driver rt5682_i2c_driver = { +static struct i2c_driver __maybe_unused rt5682_i2c_driver = { .driver = { .name = "rt5682", .of_match_table = of_match_ptr(rt5682_of_match), @@ -3713,7 +3713,10 @@ static struct i2c_driver rt5682_i2c_driver = { .shutdown = rt5682_i2c_shutdown, .id_table = rt5682_i2c_id, }; + +#ifdef CONFIG_I2C module_i2c_driver(rt5682_i2c_driver); +#endif MODULE_DESCRIPTION("ASoC RT5682 driver"); MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index f883c9340eee..69f3af4524ab 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -50,6 +50,8 @@ static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv, { int ret = 0; + WARN_ON(!mutex_is_locked(&drv->lock)); + ret = sst_fill_byte_control(drv, ipc_msg, block, task_id, pipe_id, len, cmd_data); if (ret < 0) @@ -966,7 +968,9 @@ static int sst_set_be_modules(struct snd_soc_dapm_widget *w, dev_dbg(c->dev, "Enter: widget=%s\n", w->name); if (SND_SOC_DAPM_EVENT_ON(event)) { + mutex_lock(&drv->lock); ret = sst_send_slot_map(drv); + mutex_unlock(&drv->lock); if (ret) return ret; ret = sst_send_pipe_module_params(w, k); diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c index 13db2854db3e..053c27707147 100644 --- a/sound/soc/intel/atom/sst/sst_pvt.c +++ b/sound/soc/intel/atom/sst/sst_pvt.c @@ -223,9 +223,9 @@ int sst_prepare_and_post_msg(struct intel_sst_drv *sst, size_t mbox_data_len, const void *mbox_data, void **data, bool large, bool fill_dsp, bool sync, bool response) { + struct sst_block *block = NULL; struct ipc_post *msg = NULL; struct ipc_dsp_hdr dsp_hdr; - struct sst_block *block; int ret = 0, pvt_id; pvt_id = sst_assign_pvt_id(sst); diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index 6c2fdb5659ed..af2f50293208 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -254,7 +254,6 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = broadwell_ssp0_fixup, .ops = &bdw_rt5650_ops, diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 6b4b64098d36..cc41a348295e 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -340,7 +340,6 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = broadwell_ssp0_fixup, .ops = &bdw_rt5677_ops, diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index acb4e36682cb..f9a8336a0541 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -217,7 +217,6 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .init = broadwell_rt286_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = broadwell_ssp0_fixup, .ops = &broadwell_rt286_ops, diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 33fb8ea4e5cb..08f4ae964b02 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -591,6 +591,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { + /* MPMAN MPWIN895CL */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"), + }, + .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { /* MSI S100 tablet */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 3ed53d7db4e6..74af090f2657 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -162,7 +162,6 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = haswell_ssp0_fixup, .ops = &haswell_rt5640_ops, diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index f6c7cddf08e8..125af00bba53 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -78,7 +78,7 @@ struct q6asm_dai_data { }; static const struct snd_pcm_hardware q6asm_dai_hardware_capture = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | @@ -100,7 +100,7 @@ static const struct snd_pcm_hardware q6asm_dai_hardware_capture = { }; static struct snd_pcm_hardware q6asm_dai_hardware_playback = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 19142f6e533c..8f3cad8db89a 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -295,12 +295,12 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, { int ret = 0; - if (!dai->started && + if (!dai->started[substream->stream] && dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); if (ret == 0) - dai->started = 1; + dai->started[substream->stream] = 1; return ret; } @@ -308,11 +308,11 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->started && + if (dai->started[substream->stream] && dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); - dai->started = 0; + dai->started[substream->stream] = 0; } int snd_soc_dai_prepare(struct snd_soc_dai *dai, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 04da7928c873..679ed60d850e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -802,7 +802,13 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, val = max - val; p->connect = !!val; } else { - p->connect = 0; + /* since a virtual mixer has no backing registers to + * decide which path to connect, it will try to match + * with initial state. This is to ensure + * that the default mixer choice will be + * correctly powered up during initialization. + */ + p->connect = invert; } } diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 652657dc6809..55ffb34be95e 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -825,7 +825,7 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1<<regwshift)-1; + unsigned int regwmask = (1UL<<regwshift)-1; unsigned int invert = mc->invert; unsigned long mask = (1UL<<mc->nbits)-1; long min = mc->min; @@ -874,7 +874,7 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1<<regwshift)-1; + unsigned int regwmask = (1UL<<regwshift)-1; unsigned int invert = mc->invert; unsigned long mask = (1UL<<mc->nbits)-1; long max = mc->max; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e256d438ee68..289aebc15529 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2324,7 +2324,8 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) continue; ret = dpcm_do_trigger(dpcm, be_substream, cmd); @@ -2354,7 +2355,8 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; case SNDRV_PCM_TRIGGER_STOP: - if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) continue; if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 1f81cd2d29cf..87f75edba3dc 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -362,7 +362,7 @@ static int soc_tplg_add_kcontrol(struct soc_tplg *tplg, struct snd_soc_component *comp = tplg->comp; return soc_tplg_add_dcontrol(comp->card->snd_card, - comp->dev, k, NULL, comp, kcontrol); + comp->dev, k, comp->name_prefix, comp, kcontrol); } /* remove a mixer kcontrol */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 1f2e0be812bd..64af08293daa 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -597,7 +597,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) } if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) - dev_info(sdev->dev, "firmware boot complete\n"); + dev_dbg(sdev->dev, "firmware boot complete\n"); else return -EIO; /* FW boots but fw_ready op failed */ diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 2bd280c01c33..0d0c9afd8791 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1556,8 +1556,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret = snd_soc_register_component(&pdev->dev, &stm32_component, &sai->cpu_dai_drv, 1); - if (ret) + if (ret) { + snd_dmaengine_pcm_unregister(&pdev->dev); return ret; + } if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) conf = &stm32_sai_pcm_config_spdif; diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 5ebca8013840..72b575c34860 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -359,6 +359,14 @@ static const struct usbmix_name_map corsair_virtuoso_map[] = { { 0 } }; +/* Some mobos shipped with a dummy HD-audio show the invalid GET_MIN/GET_MAX + * response for Input Gain Pad (id=19, control=12). Skip it. + */ +static const struct usbmix_name_map asus_rog_map[] = { + { 19, NULL, 12 }, /* FU, Input Gain Pad */ + {} +}; + /* * Control map entries */ @@ -488,6 +496,26 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x1b1c, 0x0a42), .map = corsair_virtuoso_map, }, + { /* Gigabyte TRX40 Aorus Pro WiFi */ + .id = USB_ID(0x0414, 0xa002), + .map = asus_rog_map, + }, + { /* ASUS ROG Zenith II */ + .id = USB_ID(0x0b05, 0x1916), + .map = asus_rog_map, + }, + { /* ASUS ROG Strix */ + .id = USB_ID(0x0b05, 0x1917), + .map = asus_rog_map, + }, + { /* MSI TRX40 Creator */ + .id = USB_ID(0x0db0, 0x0d64), + .map = asus_rog_map, + }, + { /* MSI TRX40 */ + .id = USB_ID(0x0db0, 0x543d), + .map = asus_rog_map, + }, { 0 } /* terminator */ }; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 1c8719292eee..e009d584e7d0 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3592,5 +3592,47 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * Pioneer DJ DJM-250MK2 + * PCM is 8 channels out @ 48 fixed (endpoints 0x01). + * The output from computer to the mixer is usable. + * + * The input (phono or line to computer) is not working. + * It should be at endpoint 0x82 and probably also 8 channels, + * but it seems that it works only with Pioneer proprietary software. + * Even on officially supported OS, the Audacity was unable to record + * and Mixxx to recognize the control vinyls. + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0017), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, // outputs + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 48000 } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 86f192a3043d..a8ece1701068 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1827,6 +1827,7 @@ struct registration_quirk { static const struct registration_quirk registration_quirks[] = { REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ + REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ { 0 } /* terminator */ }; |