提交 44ada1a1 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Compaq Presario CQ60 patching for Conexant
  sound: usb-audio: make the MotU Fastlane work again
  ALSA: Enable PCM hw_ptr_jiffies check only in xrun_debug mode
  ALSA: Fix invalid jiffies check after pause
...@@ -104,6 +104,11 @@ card*/pcm*/xrun_debug ...@@ -104,6 +104,11 @@ card*/pcm*/xrun_debug
When this value is greater than 1, the driver will show the When this value is greater than 1, the driver will show the
stack trace additionally. This may help the debugging. stack trace additionally. This may help the debugging.
Since 2.6.30, this option also enables the hwptr check using
jiffies. This detects spontaneous invalid pointer callback
values, but can be lead to too much corrections for a (mostly
buggy) hardware that doesn't give smooth pointer updates.
card*/pcm*/sub*/info card*/pcm*/sub*/info
The general information of this PCM sub-stream. The general information of this PCM sub-stream.
......
...@@ -249,6 +249,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) ...@@ -249,6 +249,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
new_hw_ptr = hw_base + pos; new_hw_ptr = hw_base + pos;
} }
} }
/* Do jiffies check only in xrun_debug mode */
if (!xrun_debug(substream))
goto no_jiffies_check;
/* Skip the jiffies check for hardwares with BATCH flag. /* Skip the jiffies check for hardwares with BATCH flag.
* Such hardware usually just increases the position at each IRQ, * Such hardware usually just increases the position at each IRQ,
* thus it can't give any strange position. * thus it can't give any strange position.
...@@ -336,7 +341,9 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) ...@@ -336,7 +341,9 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
hw_base = 0; hw_base = 0;
new_hw_ptr = hw_base + pos; new_hw_ptr = hw_base + pos;
} }
if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { /* Do jiffies check only in xrun_debug mode */
if (xrun_debug(substream) &&
((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
hw_ptr_error(substream, hw_ptr_error(substream,
"hw_ptr skipping! " "hw_ptr skipping! "
"(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
...@@ -1478,7 +1485,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, ...@@ -1478,7 +1485,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
runtime->status->hw_ptr %= runtime->buffer_size; runtime->status->hw_ptr %= runtime->buffer_size;
else else
runtime->status->hw_ptr = 0; runtime->status->hw_ptr = 0;
runtime->hw_ptr_jiffies = jiffies;
snd_pcm_stream_unlock_irqrestore(substream, flags); snd_pcm_stream_unlock_irqrestore(substream, flags);
return 0; return 0;
} }
......
...@@ -848,6 +848,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) ...@@ -848,6 +848,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream); snd_pcm_trigger_tstamp(substream);
runtime->hw_ptr_jiffies = jiffies;
runtime->status->state = state; runtime->status->state = state;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0) runtime->silence_size > 0)
...@@ -961,6 +962,11 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) ...@@ -961,6 +962,11 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
{ {
if (substream->runtime->trigger_master != substream) if (substream->runtime->trigger_master != substream)
return 0; return 0;
/* The jiffies check in snd_pcm_update_hw_ptr*() is done by
* a delta betwen the current jiffies, this gives a large enough
* delta, effectively to skip the check once.
*/
substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
return substream->ops->trigger(substream, return substream->ops->trigger(substream,
push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
SNDRV_PCM_TRIGGER_PAUSE_RELEASE); SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
......
...@@ -1848,6 +1848,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = { ...@@ -1848,6 +1848,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
static struct snd_pci_quirk cxt5051_cfg_tbl[] = { static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5051_LAPTOP), CXT5051_LAPTOP),
SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
......
...@@ -3347,7 +3347,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, ...@@ -3347,7 +3347,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface, [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface,
[QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface, [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface,
[QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
[QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, [QUIRK_MIDI_FASTLANE] = snd_usb_create_midi_interface,
[QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
[QUIRK_MIDI_CME] = snd_usb_create_midi_interface, [QUIRK_MIDI_CME] = snd_usb_create_midi_interface,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
......
...@@ -153,7 +153,7 @@ enum quirk_type { ...@@ -153,7 +153,7 @@ enum quirk_type {
QUIRK_MIDI_YAMAHA, QUIRK_MIDI_YAMAHA,
QUIRK_MIDI_MIDIMAN, QUIRK_MIDI_MIDIMAN,
QUIRK_MIDI_NOVATION, QUIRK_MIDI_NOVATION,
QUIRK_MIDI_RAW, QUIRK_MIDI_FASTLANE,
QUIRK_MIDI_EMAGIC, QUIRK_MIDI_EMAGIC,
QUIRK_MIDI_CME, QUIRK_MIDI_CME,
QUIRK_MIDI_US122L, QUIRK_MIDI_US122L,
......
...@@ -1778,8 +1778,18 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip, ...@@ -1778,8 +1778,18 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break; break;
case QUIRK_MIDI_RAW: case QUIRK_MIDI_FASTLANE:
umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
/*
* Interface 1 contains isochronous endpoints, but with the same
* numbers as in interface 0. Since it is interface 1 that the
* USB core has most recently seen, these descriptors are now
* associated with the endpoint numbers. This will foul up our
* attempts to submit bulk/interrupt URBs to the endpoints in
* interface 0, so we have to make sure that the USB core looks
* again at interface 0 by calling usb_set_interface() on it.
*/
usb_set_interface(umidi->chip->dev, 0, 0);
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break; break;
case QUIRK_MIDI_EMAGIC: case QUIRK_MIDI_EMAGIC:
......
...@@ -1868,7 +1868,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -1868,7 +1868,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.data = & (const struct snd_usb_audio_quirk[]) { .data = & (const struct snd_usb_audio_quirk[]) {
{ {
.ifnum = 0, .ifnum = 0,
.type = QUIRK_MIDI_RAW .type = QUIRK_MIDI_FASTLANE
}, },
{ {
.ifnum = 1, .ifnum = 1,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册