Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 01:52:49 +0000 (18:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 01:52:49 +0000 (18:52 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: usb-audio: automatically detect feedback format
  ASoC: sound/wm9090: add missing __devexit marker
  ASoC: sound/max98088: add missing __devexit marker
  ASoC: sound/ad73311: add missing __devexit marker
  ASoC: fsl - fix build error in pcm030-audio-fabric.c
  sound/oss/sb_ess.c: delete double assignment
  ALSA: hda - Change BTL amp level on some HP notebooks

sound/oss/sb_ess.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/ad73311.c
sound/soc/codecs/max98088.c
sound/soc/codecs/wm9090.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/usb/card.h
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/urb.c

index 51a3d38..9890cf2 100644 (file)
@@ -1721,7 +1721,6 @@ printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask);
                                left  = value & 0x000000ff;
                                right = (value & 0x0000ff00) >> 8;
                        } else {                                /* Turn it off (3)  */
-                               left  = 0;
                                left  = 0;
                                right = 0;
                        }
index 82ebeb9..93fa59c 100644 (file)
@@ -5326,6 +5326,82 @@ again:
        return 0;
 }
 
+static int stac92hd83xxx_set_system_btl_amp(struct hda_codec *codec)
+{
+       if (codec->vendor_id != 0x111d7605 &&
+           codec->vendor_id != 0x111d76d1)
+               return 0;
+
+       switch (codec->subsystem_id) {
+       case 0x103c1618:
+       case 0x103c1619:
+       case 0x103c161a:
+       case 0x103c161b:
+       case 0x103c161c:
+       case 0x103c161d:
+       case 0x103c161e:
+       case 0x103c161f:
+       case 0x103c1620:
+       case 0x103c1621:
+       case 0x103c1622:
+       case 0x103c1623:
+
+       case 0x103c162a:
+       case 0x103c162b:
+
+       case 0x103c1630:
+       case 0x103c1631:
+
+       case 0x103c1633:
+
+       case 0x103c1635:
+
+       case 0x103c164f:
+
+       case 0x103c1676:
+       case 0x103c1677:
+       case 0x103c1678:
+       case 0x103c1679:
+       case 0x103c167a:
+       case 0x103c167b:
+       case 0x103c167c:
+       case 0x103c167d:
+       case 0x103c167e:
+       case 0x103c167f:
+       case 0x103c1680:
+       case 0x103c1681:
+       case 0x103c1682:
+       case 0x103c1683:
+       case 0x103c1684:
+       case 0x103c1685:
+       case 0x103c1686:
+       case 0x103c1687:
+       case 0x103c1688:
+       case 0x103c1689:
+       case 0x103c168a:
+       case 0x103c168b:
+       case 0x103c168c:
+       case 0x103c168d:
+       case 0x103c168e:
+       case 0x103c168f:
+       case 0x103c1690:
+       case 0x103c1691:
+       case 0x103c1692:
+
+       case 0x103c3587:
+       case 0x103c3588:
+       case 0x103c3589:
+       case 0x103c358a:
+
+       case 0x103c3667:
+       case 0x103c3668:
+               /* set BTL amp level to 13.43dB for louder speaker output */
+               return snd_hda_codec_write_cache(codec, codec->afg, 0,
+                                                0x7F4, 0x14);
+       }
+       return 0;
+}
+
 static int patch_stac92hd83xxx(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
@@ -5452,6 +5528,8 @@ again:
                        AC_VERB_SET_CONNECT_SEL, num_dacs);
        }
 
+       stac92hd83xxx_set_system_btl_amp(codec);
+
        codec->proc_widget_hook = stac92hd_proc_hook;
 
        return 0;
index c53955f..de799cd 100644 (file)
@@ -47,7 +47,7 @@ static int ad73311_probe(struct platform_device *pdev)
                        &soc_codec_dev_ad73311, &ad73311_dai, 1);
 }
 
-static int ad73311_remove(struct platform_device *pdev)
+static int __devexit ad73311_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
index e7a40d1..bc22ee9 100644 (file)
@@ -2051,7 +2051,7 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int max98088_i2c_remove(struct i2c_client *client)
+static int __devexit max98088_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        kfree(i2c_get_clientdata(client));
index 7a18254..99c046b 100644 (file)
@@ -665,7 +665,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int wm9090_i2c_remove(struct i2c_client *i2c)
+static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
 {
        struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
 
index fe15bb2..25f27ec 100644 (file)
@@ -24,7 +24,6 @@
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
-#include <sound/soc-of-simple.h>
 
 #include "mpc5200_dma.h"
 #include "mpc5200_psc_ac97.h"
@@ -49,7 +48,7 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = {
        .codec_dai_name = "wm9712-aux",
        .cpu_dai_name = "mpc5200-psc-ac97.1",
        .platform_name = "mpc5200-pcm-audio",
-       ..codec_name = "wm9712-codec",
+       .codec_name = "wm9712-codec",
 },
 };
 
index 1febf2f..ae4251d 100644 (file)
@@ -62,12 +62,14 @@ struct snd_usb_substream {
        unsigned int syncinterval;  /* P for adaptive mode, 0 otherwise */
        unsigned int freqn;      /* nominal sampling rate in fs/fps in Q16.16 format */
        unsigned int freqm;      /* momentary sampling rate in fs/fps in Q16.16 format */
+       int          freqshift;  /* how much to shift the feedback value to get Q16.16 */
        unsigned int freqmax;    /* maximum sampling rate, used for buffer management */
        unsigned int phase;      /* phase accumulator */
        unsigned int maxpacksize;       /* max packet size in bytes */
        unsigned int maxframesize;      /* max packet size in frames */
        unsigned int curpacksize;       /* current packet size in bytes (for capture) */
        unsigned int curframesize;      /* current packet size in frames (for capture) */
+       unsigned int syncmaxsize;       /* sync endpoint packet size */
        unsigned int fill_max: 1;       /* fill max packet size always */
        unsigned int txfr_quirk:1;      /* allow sub-frame alignment */
        unsigned int fmt_type;          /* USB audio format type (1-3) */
index f49756c..cff3a3c 100644 (file)
@@ -237,6 +237,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        subs->datainterval = fmt->datainterval;
        subs->syncpipe = subs->syncinterval = 0;
        subs->maxpacksize = fmt->maxpacksize;
+       subs->syncmaxsize = 0;
        subs->fill_max = 0;
 
        /* we need a sync pipe in async OUT or adaptive IN mode */
@@ -283,6 +284,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
                        subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
                else
                        subs->syncinterval = 3;
+               subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
        }
 
        /* always fill max packet size */
index 3c650ab..961c9a2 100644 (file)
@@ -132,6 +132,11 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
                            ? get_full_speed_hz(subs->freqm)
                            : get_high_speed_hz(subs->freqm),
                            subs->freqm >> 16, subs->freqm & 0xffff);
+               if (subs->freqshift != INT_MIN)
+                       snd_iprintf(buffer, "    Feedback Format = %d.%d\n",
+                                   (subs->syncmaxsize > 3 ? 32 : 24)
+                                               - (16 - subs->freqshift),
+                                   16 - subs->freqshift);
        } else {
                snd_iprintf(buffer, "  Status: Stop\n");
        }
index 8deeaad..e184349 100644 (file)
@@ -225,6 +225,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
        else
                subs->freqn = get_usb_high_speed_rate(rate);
        subs->freqm = subs->freqn;
+       subs->freqshift = INT_MIN;
        /* calculate max. frequency */
        if (subs->maxpacksize) {
                /* whatever fits into a max. size packet */
@@ -513,11 +514,10 @@ static int retire_paused_capture_urb(struct snd_usb_substream *subs,
 
 
 /*
- * prepare urb for full speed playback sync pipe
+ * prepare urb for playback sync pipe
  *
  * set up the offset and length to receive the current frequency.
  */
-
 static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
                                     struct snd_pcm_runtime *runtime,
                                     struct urb *urb)
@@ -525,103 +525,78 @@ static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
        struct snd_urb_ctx *ctx = urb->context;
 
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->iso_frame_desc[0].length = 3;
+       urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
        urb->iso_frame_desc[0].offset = 0;
        return 0;
 }
 
 /*
- * prepare urb for high speed playback sync pipe
+ * process after playback sync complete
  *
- * set up the offset and length to receive the current frequency.
- */
-
-static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs,
-                                       struct snd_pcm_runtime *runtime,
-                                       struct urb *urb)
-{
-       struct snd_urb_ctx *ctx = urb->context;
-
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->iso_frame_desc[0].length = 4;
-       urb->iso_frame_desc[0].offset = 0;
-       return 0;
-}
-
-/*
- * process after full speed playback sync complete
- *
- * retrieve the current 10.14 frequency from pipe, and set it.
- * the value is referred in prepare_playback_urb().
+ * Full speed devices report feedback values in 10.14 format as samples per
+ * frame, high speed devices in 16.16 format as samples per microframe.
+ * Because the Audio Class 1 spec was written before USB 2.0, many high speed
+ * devices use a wrong interpretation, some others use an entirely different
+ * format.  Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
  */
 static int retire_playback_sync_urb(struct snd_usb_substream *subs,
                                    struct snd_pcm_runtime *runtime,
                                    struct urb *urb)
 {
        unsigned int f;
+       int shift;
        unsigned long flags;
 
-       if (urb->iso_frame_desc[0].status == 0 &&
-           urb->iso_frame_desc[0].actual_length == 3) {
-               f = combine_triple((u8*)urb->transfer_buffer) << 2;
-               if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
-                       spin_lock_irqsave(&subs->lock, flags);
-                       subs->freqm = f;
-                       spin_unlock_irqrestore(&subs->lock, flags);
-               }
-       }
-
-       return 0;
-}
+       if (urb->iso_frame_desc[0].status != 0 ||
+           urb->iso_frame_desc[0].actual_length < 3)
+               return 0;
 
-/*
- * process after high speed playback sync complete
- *
- * retrieve the current 12.13 frequency from pipe, and set it.
- * the value is referred in prepare_playback_urb().
- */
-static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
-                                      struct snd_pcm_runtime *runtime,
-                                      struct urb *urb)
-{
-       unsigned int f;
-       unsigned long flags;
+       f = le32_to_cpup(urb->transfer_buffer);
+       if (urb->iso_frame_desc[0].actual_length == 3)
+               f &= 0x00ffffff;
+       else
+               f &= 0x0fffffff;
+       if (f == 0)
+               return 0;
 
-       if (urb->iso_frame_desc[0].status == 0 &&
-           urb->iso_frame_desc[0].actual_length == 4) {
-               f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
-               if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
-                       spin_lock_irqsave(&subs->lock, flags);
-                       subs->freqm = f;
-                       spin_unlock_irqrestore(&subs->lock, flags);
+       if (unlikely(subs->freqshift == INT_MIN)) {
+               /*
+                * The first time we see a feedback value, determine its format
+                * by shifting it left or right until it matches the nominal
+                * frequency value.  This assumes that the feedback does not
+                * differ from the nominal value more than +50% or -25%.
+                */
+               shift = 0;
+               while (f < subs->freqn - subs->freqn / 4) {
+                       f <<= 1;
+                       shift++;
+               }
+               while (f > subs->freqn + subs->freqn / 2) {
+                       f >>= 1;
+                       shift--;
                }
+               subs->freqshift = shift;
        }
+       else if (subs->freqshift >= 0)
+               f <<= subs->freqshift;
+       else
+               f >>= -subs->freqshift;
 
-       return 0;
-}
-
-/*
- * process after E-Mu 0202/0404/Tracker Pre high speed playback sync complete
- *
- * These devices return the number of samples per packet instead of the number
- * of samples per microframe.
- */
-static int retire_playback_sync_urb_hs_emu(struct snd_usb_substream *subs,
-                                          struct snd_pcm_runtime *runtime,
-                                          struct urb *urb)
-{
-       unsigned int f;
-       unsigned long flags;
-
-       if (urb->iso_frame_desc[0].status == 0 &&
-           urb->iso_frame_desc[0].actual_length == 4) {
-               f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
-               f >>= subs->datainterval;
-               if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
-                       spin_lock_irqsave(&subs->lock, flags);
-                       subs->freqm = f;
-                       spin_unlock_irqrestore(&subs->lock, flags);
-               }
+       if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
+               /*
+                * If the frequency looks valid, set it.
+                * This value is referred to in prepare_playback_urb().
+                */
+               spin_lock_irqsave(&subs->lock, flags);
+               subs->freqm = f;
+               spin_unlock_irqrestore(&subs->lock, flags);
+       } else {
+               /*
+                * Out of range; maybe the shift value is wrong.
+                * Reset it so that we autodetect again the next time.
+                */
+               subs->freqshift = INT_MIN;
        }
 
        return 0;
@@ -878,21 +853,6 @@ static struct snd_urb_ops audio_urb_ops[2] = {
        },
 };
 
-static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
-       {
-               .prepare =      prepare_nodata_playback_urb,
-               .retire =       retire_playback_urb,
-               .prepare_sync = prepare_playback_sync_urb_hs,
-               .retire_sync =  retire_playback_sync_urb_hs,
-       },
-       {
-               .prepare =      prepare_capture_urb,
-               .retire =       retire_capture_urb,
-               .prepare_sync = prepare_capture_sync_urb_hs,
-               .retire_sync =  retire_capture_sync_urb,
-       },
-};
-
 /*
  * initialize the substream instance.
  */
@@ -909,23 +869,9 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->direction = stream;
        subs->dev = as->chip->dev;
        subs->txfr_quirk = as->chip->txfr_quirk;
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) {
-               subs->ops = audio_urb_ops[stream];
-       } else {
-               subs->ops = audio_urb_ops_high_speed[stream];
-               switch (as->chip->usb_id) {
-               case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
-               case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
-               case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
-                       subs->ops.retire_sync = retire_playback_sync_urb_hs_emu;
-                       break;
-               case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8  */
-               case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
-                       subs->ops.prepare_sync = prepare_playback_sync_urb;
-                       subs->ops.retire_sync = retire_playback_sync_urb;
-                       break;
-               }
-       }
+       subs->ops = audio_urb_ops[stream];
+       if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
+               subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
 
        snd_usb_set_pcm_ops(as->pcm, stream);