]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/em28xx/em28xx-audio.c
V4L/DVB (9742): em28xx-alsa: implement another locking schema
[linux-2.6-omap-h63xx.git] / drivers / media / video / em28xx / em28xx-audio.c
index 3c006103c1eb369c4817fd74522ef7ffebc91e61..dfac2e042a52dc5a87d85a1b126928d87f4d03b4 100644 (file)
@@ -75,7 +75,9 @@ static void em28xx_audio_isocirq(struct urb *urb)
        struct em28xx            *dev = urb->context;
        int                      i;
        unsigned int             oldptr;
+#ifdef NO_PCM_LOCK
        unsigned long            flags;
+#endif
        int                      period_elapsed = 0;
        int                      status;
        unsigned char            *cp;
@@ -96,9 +98,26 @@ static void em28xx_audio_isocirq(struct urb *urb)
                        if (!length)
                                continue;
 
+#ifdef NO_PCM_LOCK
                        spin_lock_irqsave(&dev->adev->slock, flags);
-
+#endif
                        oldptr = dev->adev->hwptr_done_capture;
+                       if (oldptr + length >= runtime->buffer_size) {
+                               unsigned int cnt =
+                                   runtime->buffer_size - oldptr;
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      cnt * stride);
+                               memcpy(runtime->dma_area, cp + cnt * stride,
+                                      length * stride - cnt * stride);
+                       } else {
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      length * stride);
+                       }
+
+#ifndef NO_PCM_LOCK
+                       snd_pcm_stream_lock(substream);
+#endif
+
                        dev->adev->hwptr_done_capture += length;
                        if (dev->adev->hwptr_done_capture >=
                            runtime->buffer_size)
@@ -113,19 +132,11 @@ static void em28xx_audio_isocirq(struct urb *urb)
                                period_elapsed = 1;
                        }
 
+#ifdef NO_PCM_LOCK
                        spin_unlock_irqrestore(&dev->adev->slock, flags);
-
-                       if (oldptr + length >= runtime->buffer_size) {
-                               unsigned int cnt =
-                                   runtime->buffer_size - oldptr - 1;
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      cnt * stride);
-                               memcpy(runtime->dma_area, cp + cnt,
-                                      length * stride - cnt * stride);
-                       } else {
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      length * stride);
-                       }
+#else
+                       snd_pcm_stream_unlock(substream);
+#endif
                }
                if (period_elapsed)
                        snd_pcm_period_elapsed(substream);
@@ -161,8 +172,14 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
 
                memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
                urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
-               if (!urb)
+               if (!urb) {
+                       em28xx_errdev("usb_alloc_urb failed!\n");
+                       for (j = 0; j < i; j++) {
+                               usb_free_urb(dev->adev->urb[j]);
+                               kfree(dev->adev->transfer_buffer[j]);
+                       }
                        return -ENOMEM;
+               }
 
                urb->dev = dev->udev;
                urb->context = dev;