Commit c6c96d7b authored by Linus Torvalds's avatar Linus Torvalds

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

Pull sound fixes from Takashi Iwai:
 "A bunch of small fixes for USB-audio and HD-audio, where most of them
  are for regressions: USB-audio PM fixes, ratelimit annoyance fix, HDMI
  offline state fix, and a couple of device-specific quirks"

* tag 'sound-3.15-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - hdmi: Set converter channel count even without sink
  ALSA: usb-audio: work around corrupted TEAC UD-H01 feedback data
  ALSA: usb-audio: Fix deadlocks at resuming
  ALSA: usb-audio: Save mixer status only once at suspend
  ALSA: usb-audio: Prevent printk ratelimiting from spamming kernel log while DEBUG not defined
  ALSA: hda - add headset mic detect quirk for a Dell laptop
parents 1b826a94 f06ab794
...@@ -1127,8 +1127,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, ...@@ -1127,8 +1127,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
AMP_OUT_UNMUTE); AMP_OUT_UNMUTE);
eld = &per_pin->sink_eld; eld = &per_pin->sink_eld;
if (!eld->monitor_present) if (!eld->monitor_present) {
hdmi_set_channel_count(codec, per_pin->cvt_nid, channels);
return; return;
}
if (!non_pcm && per_pin->chmap_set) if (!non_pcm && per_pin->chmap_set)
ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
......
...@@ -4622,6 +4622,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -4622,6 +4622,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
......
...@@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) ...@@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
int err = -ENODEV; int err = -ENODEV;
down_read(&chip->shutdown_rwsem); down_read(&chip->shutdown_rwsem);
if (chip->probing) if (chip->probing && chip->in_pm)
err = 0; err = 0;
else if (!chip->shutdown) else if (!chip->shutdown)
err = usb_autopm_get_interface(chip->pm_intf); err = usb_autopm_get_interface(chip->pm_intf);
...@@ -663,7 +663,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) ...@@ -663,7 +663,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
void snd_usb_autosuspend(struct snd_usb_audio *chip) void snd_usb_autosuspend(struct snd_usb_audio *chip)
{ {
down_read(&chip->shutdown_rwsem); down_read(&chip->shutdown_rwsem);
if (!chip->shutdown && !chip->probing) if (!chip->shutdown && !chip->probing && !chip->in_pm)
usb_autopm_put_interface(chip->pm_intf); usb_autopm_put_interface(chip->pm_intf);
up_read(&chip->shutdown_rwsem); up_read(&chip->shutdown_rwsem);
} }
...@@ -695,6 +695,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -695,6 +695,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
chip->autosuspended = 1; chip->autosuspended = 1;
} }
if (chip->num_suspended_intf == 1)
list_for_each_entry(mixer, &chip->mixer_list, list) list_for_each_entry(mixer, &chip->mixer_list, list)
snd_usb_mixer_suspend(mixer); snd_usb_mixer_suspend(mixer);
...@@ -711,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) ...@@ -711,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
return 0; return 0;
if (--chip->num_suspended_intf) if (--chip->num_suspended_intf)
return 0; return 0;
chip->in_pm = 1;
/* /*
* ALSA leaves material resumption to user space * ALSA leaves material resumption to user space
* we just notify and restart the mixers * we just notify and restart the mixers
...@@ -726,6 +729,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) ...@@ -726,6 +729,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
chip->autosuspended = 0; chip->autosuspended = 0;
err_out: err_out:
chip->in_pm = 0;
return err; return err;
} }
......
...@@ -92,6 +92,7 @@ struct snd_usb_endpoint { ...@@ -92,6 +92,7 @@ struct snd_usb_endpoint {
unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int curframesize; /* current packet size in frames (for capture) */
unsigned int syncmaxsize; /* sync endpoint packet size */ unsigned int syncmaxsize; /* sync endpoint packet size */
unsigned int fill_max:1; /* fill max packet size always */ unsigned int fill_max:1; /* fill max packet size always */
unsigned int udh01_fb_quirk:1; /* corrupted feedback data */
unsigned int datainterval; /* log_2 of data packet interval */ unsigned int datainterval; /* log_2 of data packet interval */
unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
unsigned char silence_value; unsigned char silence_value;
......
...@@ -471,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, ...@@ -471,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
ep->syncinterval = 3; ep->syncinterval = 3;
ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ &&
ep->syncmaxsize == 4)
ep->udh01_fb_quirk = 1;
} }
list_add_tail(&ep->list, &chip->ep_list); list_add_tail(&ep->list, &chip->ep_list);
...@@ -1105,7 +1109,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, ...@@ -1105,7 +1109,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
if (f == 0) if (f == 0)
return; return;
if (unlikely(ep->freqshift == INT_MIN)) { if (unlikely(sender->udh01_fb_quirk)) {
/*
* The TEAC UD-H01 firmware sometimes changes the feedback value
* by +/- 0x1.0000.
*/
if (f < ep->freqn - 0x8000)
f += 0x10000;
else if (f > ep->freqn + 0x8000)
f -= 0x10000;
} else if (unlikely(ep->freqshift == INT_MIN)) {
/* /*
* The first time we see a feedback value, determine its format * The first time we see a feedback value, determine its format
* by shifting it left or right until it matches the nominal * by shifting it left or right until it matches the nominal
......
...@@ -1501,9 +1501,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs, ...@@ -1501,9 +1501,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
* The error should be lower than 2ms since the estimate relies * The error should be lower than 2ms since the estimate relies
* on two reads of a counter updated every ms. * on two reads of a counter updated every ms.
*/ */
if (printk_ratelimit() && if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) dev_dbg_ratelimited(&subs->dev->dev,
dev_dbg(&subs->dev->dev,
"delay: estimated %d, actual %d\n", "delay: estimated %d, actual %d\n",
est_delay, subs->last_delay); est_delay, subs->last_delay);
......
...@@ -40,6 +40,7 @@ struct snd_usb_audio { ...@@ -40,6 +40,7 @@ struct snd_usb_audio {
struct rw_semaphore shutdown_rwsem; struct rw_semaphore shutdown_rwsem;
unsigned int shutdown:1; unsigned int shutdown:1;
unsigned int probing:1; unsigned int probing:1;
unsigned int in_pm:1;
unsigned int autosuspended:1; unsigned int autosuspended:1;
unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment