Commit 20ebba65 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa:
  [ALSA] version 1.0.13
  [ALSA] sound/pci/au88x0/au88x0.c: ioremap balanced with iounmap
  [ALSA] Handle file operations during snd_card disconnects using static file->f_op
  [ALSA] emu10k1: Fix outl() in snd_emu10k1_resume_regs()
  [ALSA] Repair snd-usb-usx2y for usb 2.6.18
  [ALSA] Fix bug in snd-usb-usx2y's usX2Y_pcms_lock_check()
  [ALSA] Dereference after free in snd_hwdep_release()
  [ALSA] Fix memory leak in sound/isa/es18xx.c
  [ALSA] hda-intel - New pci id for Nvidia MCP61
  [ALSA] Add new subdevice ids for hda-intel
  [ALSA] WM9712 fixes for ac97_patch.c
  [ALSA] hda/patch_si3054: new codec vendor IDs
parents 815a965b 5a078351
...@@ -89,10 +89,10 @@ struct snd_device { ...@@ -89,10 +89,10 @@ struct snd_device {
struct snd_monitor_file { struct snd_monitor_file {
struct file *file; struct file *file;
struct snd_monitor_file *next; struct snd_monitor_file *next;
const struct file_operations *disconnected_f_op;
struct list_head shutdown_list;
}; };
struct snd_shutdown_f_ops; /* define it later in init.c */
/* main structure for soundcard */ /* main structure for soundcard */
struct snd_card { struct snd_card {
......
/* include/version.h. Generated by configure. */ /* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.12rc1" #define CONFIG_SND_VERSION "1.0.13"
#define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)" #define CONFIG_SND_DATE " (Fri Oct 06 18:28:19 2006 UTC)"
...@@ -158,6 +158,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file) ...@@ -158,6 +158,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
{ {
int err = -ENXIO; int err = -ENXIO;
struct snd_hwdep *hw = file->private_data; struct snd_hwdep *hw = file->private_data;
struct module *mod = hw->card->module;
mutex_lock(&hw->open_mutex); mutex_lock(&hw->open_mutex);
if (hw->ops.release) { if (hw->ops.release) {
err = hw->ops.release(hw, file); err = hw->ops.release(hw, file);
...@@ -167,7 +168,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file) ...@@ -167,7 +168,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
hw->used--; hw->used--;
snd_card_file_remove(hw->card, file); snd_card_file_remove(hw->card, file);
mutex_unlock(&hw->open_mutex); mutex_unlock(&hw->open_mutex);
module_put(hw->card->module); module_put(mod);
return err; return err;
} }
......
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
#include <sound/control.h> #include <sound/control.h>
#include <sound/info.h> #include <sound/info.h>
struct snd_shutdown_f_ops { static DEFINE_SPINLOCK(shutdown_lock);
struct file_operations f_ops; static LIST_HEAD(shutdown_files);
struct snd_shutdown_f_ops *next;
}; static struct file_operations snd_shutdown_f_ops;
static unsigned int snd_cards_lock; /* locked for registering/using */ static unsigned int snd_cards_lock; /* locked for registering/using */
struct snd_card *snd_cards[SNDRV_CARDS]; struct snd_card *snd_cards[SNDRV_CARDS];
...@@ -198,6 +198,25 @@ static ssize_t snd_disconnect_write(struct file *file, const char __user *buf, ...@@ -198,6 +198,25 @@ static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
return -ENODEV; return -ENODEV;
} }
static int snd_disconnect_release(struct inode *inode, struct file *file)
{
struct snd_monitor_file *df = NULL, *_df;
spin_lock(&shutdown_lock);
list_for_each_entry(_df, &shutdown_files, shutdown_list) {
if (_df->file == file) {
df = _df;
break;
}
}
spin_unlock(&shutdown_lock);
if (likely(df))
return df->disconnected_f_op->release(inode, file);
panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
}
static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait) static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
{ {
return POLLERR | POLLNVAL; return POLLERR | POLLNVAL;
...@@ -219,6 +238,22 @@ static int snd_disconnect_fasync(int fd, struct file *file, int on) ...@@ -219,6 +238,22 @@ static int snd_disconnect_fasync(int fd, struct file *file, int on)
return -ENODEV; return -ENODEV;
} }
static struct file_operations snd_shutdown_f_ops =
{
.owner = THIS_MODULE,
.llseek = snd_disconnect_llseek,
.read = snd_disconnect_read,
.write = snd_disconnect_write,
.release = snd_disconnect_release,
.poll = snd_disconnect_poll,
.unlocked_ioctl = snd_disconnect_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = snd_disconnect_ioctl,
#endif
.mmap = snd_disconnect_mmap,
.fasync = snd_disconnect_fasync
};
/** /**
* snd_card_disconnect - disconnect all APIs from the file-operations (user space) * snd_card_disconnect - disconnect all APIs from the file-operations (user space)
* @card: soundcard structure * @card: soundcard structure
...@@ -234,9 +269,6 @@ int snd_card_disconnect(struct snd_card *card) ...@@ -234,9 +269,6 @@ int snd_card_disconnect(struct snd_card *card)
{ {
struct snd_monitor_file *mfile; struct snd_monitor_file *mfile;
struct file *file; struct file *file;
struct snd_shutdown_f_ops *s_f_ops;
struct file_operations *f_ops;
const struct file_operations *old_f_ops;
int err; int err;
spin_lock(&card->files_lock); spin_lock(&card->files_lock);
...@@ -261,34 +293,14 @@ int snd_card_disconnect(struct snd_card *card) ...@@ -261,34 +293,14 @@ int snd_card_disconnect(struct snd_card *card)
/* it's critical part, use endless loop */ /* it's critical part, use endless loop */
/* we have no room to fail */ /* we have no room to fail */
s_f_ops = kmalloc(sizeof(struct snd_shutdown_f_ops), GFP_ATOMIC); mfile->disconnected_f_op = mfile->file->f_op;
if (s_f_ops == NULL)
panic("Atomic allocation failed for snd_shutdown_f_ops!");
f_ops = &s_f_ops->f_ops;
memset(f_ops, 0, sizeof(*f_ops));
f_ops->owner = file->f_op->owner;
f_ops->release = file->f_op->release;
f_ops->llseek = snd_disconnect_llseek;
f_ops->read = snd_disconnect_read;
f_ops->write = snd_disconnect_write;
f_ops->poll = snd_disconnect_poll;
f_ops->unlocked_ioctl = snd_disconnect_ioctl;
#ifdef CONFIG_COMPAT
f_ops->compat_ioctl = snd_disconnect_ioctl;
#endif
f_ops->mmap = snd_disconnect_mmap;
f_ops->fasync = snd_disconnect_fasync;
s_f_ops->next = card->s_f_ops;
card->s_f_ops = s_f_ops;
f_ops = fops_get(f_ops); spin_lock(&shutdown_lock);
list_add(&mfile->shutdown_list, &shutdown_files);
spin_unlock(&shutdown_lock);
old_f_ops = file->f_op; fops_get(&snd_shutdown_f_ops);
file->f_op = f_ops; /* must be atomic */ mfile->file->f_op = &snd_shutdown_f_ops;
fops_put(old_f_ops);
mfile = mfile->next; mfile = mfile->next;
} }
...@@ -326,8 +338,6 @@ EXPORT_SYMBOL(snd_card_disconnect); ...@@ -326,8 +338,6 @@ EXPORT_SYMBOL(snd_card_disconnect);
*/ */
static int snd_card_do_free(struct snd_card *card) static int snd_card_do_free(struct snd_card *card)
{ {
struct snd_shutdown_f_ops *s_f_ops;
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback) if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
...@@ -351,11 +361,6 @@ static int snd_card_do_free(struct snd_card *card) ...@@ -351,11 +361,6 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n"); snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */ /* Not fatal error */
} }
while (card->s_f_ops) {
s_f_ops = card->s_f_ops;
card->s_f_ops = s_f_ops->next;
kfree(s_f_ops);
}
kfree(card); kfree(card);
return 0; return 0;
} }
...@@ -670,6 +675,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) ...@@ -670,6 +675,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
if (mfile == NULL) if (mfile == NULL)
return -ENOMEM; return -ENOMEM;
mfile->file = file; mfile->file = file;
mfile->disconnected_f_op = NULL;
mfile->next = NULL; mfile->next = NULL;
spin_lock(&card->files_lock); spin_lock(&card->files_lock);
if (card->shutdown) { if (card->shutdown) {
...@@ -716,6 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) ...@@ -716,6 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
pfile = mfile; pfile = mfile;
mfile = mfile->next; mfile = mfile->next;
} }
if (mfile && mfile->disconnected_f_op) {
fops_put(mfile->disconnected_f_op);
spin_lock(&shutdown_lock);
list_del(&mfile->shutdown_list);
spin_unlock(&shutdown_lock);
}
if (card->files == NULL) if (card->files == NULL)
last_close = 1; last_close = 1;
spin_unlock(&card->files_lock); spin_unlock(&card->files_lock);
......
...@@ -2154,6 +2154,7 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, ...@@ -2154,6 +2154,7 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
} }
/* Control port initialization */ /* Control port initialization */
if (pnp_activate_dev(acard->devc) < 0) { if (pnp_activate_dev(acard->devc) < 0) {
kfree(cfg);
snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
return -EAGAIN; return -EAGAIN;
} }
......
...@@ -530,7 +530,7 @@ AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]), ...@@ -530,7 +530,7 @@ AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1), AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1), AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1), AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
AC97_ENUM("Out3 Mux", wm9711_enum[2]), AC97_ENUM("Out3 Mux", wm9711_enum[2]),
AC97_ENUM("Out3 LR Mux", wm9711_enum[3]), AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1), AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
...@@ -575,13 +575,14 @@ AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), ...@@ -575,13 +575,14 @@ AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1), AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
AC97_ENUM("Capture Volume Steps", wm9711_enum[6]), AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 1), AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1), AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1), AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
AC97_ENUM("Mic Select Source", wm9711_enum[7]), AC97_ENUM("Mic Select Source", wm9711_enum[7]),
AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1), AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
......
...@@ -128,6 +128,7 @@ static int snd_vortex_dev_free(struct snd_device *device) ...@@ -128,6 +128,7 @@ static int snd_vortex_dev_free(struct snd_device *device)
// Take down PCI interface. // Take down PCI interface.
synchronize_irq(vortex->irq); synchronize_irq(vortex->irq);
free_irq(vortex->irq, vortex); free_irq(vortex->irq, vortex);
iounmap(vortex->mmio);
pci_release_regions(vortex->pci_dev); pci_release_regions(vortex->pci_dev);
pci_disable_device(vortex->pci_dev); pci_disable_device(vortex->pci_dev);
kfree(vortex); kfree(vortex);
......
...@@ -1461,8 +1461,8 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) ...@@ -1461,8 +1461,8 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
/* resore for spdif */ /* resore for spdif */
if (emu->audigy) if (emu->audigy)
outl(emu->port + A_IOCFG, emu->saved_a_iocfg); outl(emu->saved_a_iocfg, emu->port + A_IOCFG);
outl(emu->port + HCFG, emu->saved_hcfg); outl(emu->saved_hcfg, emu->port + HCFG);
val = emu->saved_ptr; val = emu->saved_ptr;
for (reg = saved_regs; *reg != 0xff; reg++) for (reg = saved_regs; *reg != 0xff; reg++)
......
...@@ -1682,6 +1682,7 @@ static struct pci_device_id azx_ids[] = { ...@@ -1682,6 +1682,7 @@ static struct pci_device_id azx_ids[] = {
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */ { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */
{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */ { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */
{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 03f0 */
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, azx_ids); MODULE_DEVICE_TABLE(pci, azx_ids);
......
...@@ -5076,6 +5076,10 @@ static struct hda_board_config alc883_cfg_tbl[] = { ...@@ -5076,6 +5076,10 @@ static struct hda_board_config alc883_cfg_tbl[] = {
{ .modelname = "acer", .config = ALC883_ACER }, { .modelname = "acer", .config = ALC883_ACER },
{ .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/, { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/,
.config = ALC883_ACER }, .config = ALC883_ACER },
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0102,
.config = ALC883_ACER },
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x009f,
.config = ALC883_ACER },
{ .modelname = "auto", .config = ALC883_AUTO }, { .modelname = "auto", .config = ALC883_AUTO },
{} {}
}; };
......
...@@ -297,8 +297,13 @@ static int patch_si3054(struct hda_codec *codec) ...@@ -297,8 +297,13 @@ static int patch_si3054(struct hda_codec *codec)
struct hda_codec_preset snd_hda_preset_si3054[] = { struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c11040, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13155, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
{} {}
}; };
...@@ -322,7 +322,7 @@ static void i_usX2Y_urb_complete(struct urb *urb) ...@@ -322,7 +322,7 @@ static void i_usX2Y_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb); usX2Y_error_urb_status(usX2Y, subs, urb);
return; return;
} }
if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame)) if (likely(urb->start_frame == usX2Y->wait_iso_frame))
subs->completed_urb = urb; subs->completed_urb = urb;
else { else {
usX2Y_error_sequence(usX2Y, subs, urb); usX2Y_error_sequence(usX2Y, subs, urb);
...@@ -335,13 +335,9 @@ static void i_usX2Y_urb_complete(struct urb *urb) ...@@ -335,13 +335,9 @@ static void i_usX2Y_urb_complete(struct urb *urb)
atomic_read(&capsubs->state) >= state_PREPARED && atomic_read(&capsubs->state) >= state_PREPARED &&
(playbacksubs->completed_urb || (playbacksubs->completed_urb ||
atomic_read(&playbacksubs->state) < state_PREPARED)) { atomic_read(&playbacksubs->state) < state_PREPARED)) {
if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) { if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame))
if (nr_of_packs() <= urb->start_frame &&
urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci
usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
else
usX2Y->wait_iso_frame += nr_of_packs(); usX2Y->wait_iso_frame += nr_of_packs();
} else { else {
snd_printdd("\n"); snd_printdd("\n");
usX2Y_clients_stop(usX2Y); usX2Y_clients_stop(usX2Y);
} }
...@@ -495,7 +491,6 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) ...@@ -495,7 +491,6 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
goto start; goto start;
} }
usX2Y->wait_iso_frame = -1;
start: start:
usX2Y_subs_startup(subs); usX2Y_subs_startup(subs);
...@@ -516,10 +511,9 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) ...@@ -516,10 +511,9 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
err = -EPIPE; err = -EPIPE;
goto cleanup; goto cleanup;
} else { } else
if (0 > usX2Y->wait_iso_frame) if (i == 0)
usX2Y->wait_iso_frame = urb->start_frame; usX2Y->wait_iso_frame = urb->start_frame;
}
urb->transfer_flags = 0; urb->transfer_flags = 0;
} else { } else {
atomic_set(&subs->state, state_STARTING1); atomic_set(&subs->state, state_STARTING1);
......
...@@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) ...@@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb); usX2Y_error_urb_status(usX2Y, subs, urb);
return; return;
} }
if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame)) if (likely(urb->start_frame == usX2Y->wait_iso_frame))
subs->completed_urb = urb; subs->completed_urb = urb;
else { else {
usX2Y_error_sequence(usX2Y, subs, urb); usX2Y_error_sequence(usX2Y, subs, urb);
...@@ -256,13 +256,9 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) ...@@ -256,13 +256,9 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
(NULL == capsubs2 || capsubs2->completed_urb) && (NULL == capsubs2 || capsubs2->completed_urb) &&
(playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
if (nr_of_packs() <= urb->start_frame &&
urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci
usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
else
usX2Y->wait_iso_frame += nr_of_packs(); usX2Y->wait_iso_frame += nr_of_packs();
} else { else {
snd_printdd("\n"); snd_printdd("\n");
usX2Y_clients_stop(usX2Y); usX2Y_clients_stop(usX2Y);
} }
...@@ -433,7 +429,6 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) ...@@ -433,7 +429,6 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
goto start; goto start;
} }
usX2Y->wait_iso_frame = -1;
start: start:
usX2Y_usbpcm_subs_startup(subs); usX2Y_usbpcm_subs_startup(subs);
...@@ -459,7 +454,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) ...@@ -459,7 +454,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
goto cleanup; goto cleanup;
} else { } else {
snd_printdd("%i\n", urb->start_frame); snd_printdd("%i\n", urb->start_frame);
if (0 > usX2Y->wait_iso_frame) if (u == 0)
usX2Y->wait_iso_frame = urb->start_frame; usX2Y->wait_iso_frame = urb->start_frame;
} }
urb->transfer_flags = 0; urb->transfer_flags = 0;
...@@ -632,7 +627,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card) ...@@ -632,7 +627,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card)
for (s = 0; s < 2; ++s) { for (s = 0; s < 2; ++s) {
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
substream = pcm->streams[s].substream; substream = pcm->streams[s].substream;
if (SUBSTREAM_BUSY(substream)) if (substream && SUBSTREAM_BUSY(substream))
err = -EBUSY; err = -EBUSY;
} }
} }
......
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