Merge branch 'topic/usb-audio' into for-linus
Takashi Iwai [Wed, 10 Jun 2009 05:26:49 +0000 (07:26 +0200)]
* topic/usb-audio:
  ALSA: usb - Add boot quirk for C-Media 6206 USB Audio
  ALSA: usb-audio - errata corrige for quirk
  ALSA: usb-audio - Add quirk for Roland/Edirol M-16DX
  ALSA: usb-audio - quirk for USB Aureon cards

1  2 
sound/usb/usbaudio.c

diff --combined sound/usb/usbaudio.c
@@@ -627,7 -627,6 +627,7 @@@ static int prepare_playback_urb(struct 
        subs->hwptr_done += offs;
        if (subs->hwptr_done >= runtime->buffer_size)
                subs->hwptr_done -= runtime->buffer_size;
 +      runtime->delay += offs;
        spin_unlock_irqrestore(&subs->lock, flags);
        urb->transfer_buffer_length = offs * stride;
        if (period_elapsed)
  
  /*
   * process after playback data complete
 - * - nothing to do
 + * - decrease the delay count again
   */
  static int retire_playback_urb(struct snd_usb_substream *subs,
                               struct snd_pcm_runtime *runtime,
                               struct urb *urb)
  {
 +      unsigned long flags;
 +      int stride = runtime->frame_bits >> 3;
 +      int processed = urb->transfer_buffer_length / stride;
 +
 +      spin_lock_irqsave(&subs->lock, flags);
 +      if (processed > runtime->delay)
 +              runtime->delay = 0;
 +      else
 +              runtime->delay -= processed;
 +      spin_unlock_irqrestore(&subs->lock, flags);
        return 0;
  }
  
@@@ -1531,7 -1520,6 +1531,7 @@@ static int snd_usb_pcm_prepare(struct s
        subs->hwptr_done = 0;
        subs->transfer_done = 0;
        subs->phase = 0;
 +      runtime->delay = 0;
  
        /* clear urbs (to be sure) */
        deactivate_urbs(subs, 0, 1);
@@@ -3291,6 -3279,25 +3291,25 @@@ static int snd_usb_cm106_boot_quirk(str
        return snd_usb_cm106_write_int_reg(dev, 2, 0x8004);
  }
  
+ /*
+  * C-Media CM6206 is based on CM106 with two additional
+  * registers that are not documented in the data sheet.
+  * Values here are chosen based on sniffing USB traffic
+  * under Windows.
+  */
+ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
+ {
+       int err, reg;
+       int val[] = {0x200c, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
+       for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
+               err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]);
+               if (err < 0)
+                       return err;
+       }
+       return err;
+ }
  
  /*
   * Setup quirks
@@@ -3577,6 -3584,12 +3596,12 @@@ static void *snd_usb_audio_probe(struc
                        goto __err_val;
        }
  
+       /* C-Media CM6206 / CM106-Like Sound Device */
+       if (id == USB_ID(0x0d8c, 0x0102)) {
+               if (snd_usb_cm6206_boot_quirk(dev) < 0)
+                       goto __err_val;
+       }
        /*
         * found a config.  now register to ALSA
         */