linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / sound / usb / usx2y / usx2yhwdeppcm.c
index 3bda17d..796a7dc 100644 (file)
@@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
                usX2Y_error_urb_status(usX2Y, subs, urb);
                return;
        }
-       if (likely(urb->start_frame == usX2Y->wait_iso_frame))
+       if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame))
                subs->completed_urb = urb;
        else {
                usX2Y_error_sequence(usX2Y, subs, urb);
@@ -256,9 +256,13 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
        if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
            (NULL == capsubs2 || capsubs2->completed_urb) &&
            (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
-               if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
-                       usX2Y->wait_iso_frame += nr_of_packs();
-               else {
+               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();
+               } else {
                        snd_printdd("\n");
                        usX2Y_clients_stop(usX2Y);
                }
@@ -362,7 +366,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_usX2Y_substream *subs = runtime->private_data,
                *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
-       mutex_lock(&subs->usX2Y->prepare_mutex);
+       down(&subs->usX2Y->prepare_mutex);
        snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
 
        if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
@@ -391,7 +395,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
                                usX2Y_usbpcm_urbs_release(cap_subs2);
                }
        }
-       mutex_unlock(&subs->usX2Y->prepare_mutex);
+       up(&subs->usX2Y->prepare_mutex);
        return snd_pcm_lib_free_pages(substream);
 }
 
@@ -400,7 +404,7 @@ static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
        struct usX2Ydev * usX2Y = subs->usX2Y;
        usX2Y->prepare_subs = subs;
        subs->urb[0]->start_frame = -1;
-       smp_wmb();      // Make sure above modifications are seen by i_usX2Y_subs_startup()
+       smp_wmb();      // Make shure above modifications are seen by i_usX2Y_subs_startup()
        usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);
 }
 
@@ -429,6 +433,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
                if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
                        goto start;
        }
+       usX2Y->wait_iso_frame = -1;
 
  start:
        usX2Y_usbpcm_subs_startup(subs);
@@ -454,7 +459,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
                                                goto cleanup;
                                        }  else {
                                                snd_printdd("%i\n", urb->start_frame);
-                                               if (u == 0)
+                                               if (0 > usX2Y->wait_iso_frame)
                                                        usX2Y->wait_iso_frame = urb->start_frame;
                                        }
                                        urb->transfer_flags = 0;
@@ -498,7 +503,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
                memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
        }
 
-       mutex_lock(&usX2Y->prepare_mutex);
+       down(&usX2Y->prepare_mutex);
        usX2Y_subs_prepare(subs);
 // Start hardware streams
 // SyncStream first....
@@ -539,7 +544,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
                usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
 
  up_prepare_mutex:
-       mutex_unlock(&usX2Y->prepare_mutex);
+       up(&usX2Y->prepare_mutex);
        return err;
 }
 
@@ -616,7 +621,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card)
                if (dev->type != SNDRV_DEV_PCM)
                        continue;
                pcm = dev->device_data;
-               mutex_lock(&pcm->open_mutex);
+               down(&pcm->open_mutex);
        }
        list_for_each(list, &card->devices) {
                int s;
@@ -627,7 +632,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card)
                for (s = 0; s < 2; ++s) {
                        struct snd_pcm_substream *substream;
                        substream = pcm->streams[s].substream;
-                       if (substream && SUBSTREAM_BUSY(substream))
+                       if (substream && substream->ffile != NULL)
                                err = -EBUSY;
                }
        }
@@ -645,7 +650,7 @@ static void usX2Y_pcms_unlock(struct snd_card *card)
                if (dev->type != SNDRV_DEV_PCM)
                        continue;
                pcm = dev->device_data;
-               mutex_unlock(&pcm->open_mutex);
+               up(&pcm->open_mutex);
        }
 }