]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'fix/misc' into topic/misc
authorTakashi Iwai <tiwai@suse.de>
Wed, 17 Feb 2010 13:24:46 +0000 (14:24 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 17 Feb 2010 13:24:46 +0000 (14:24 +0100)
Conflicts:
sound/pci/hda/patch_realtek.c

1  2 
sound/core/pcm_native.c
sound/pci/atiixp.c
sound/pci/echoaudio/echoaudio.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/riptide/riptide.c
sound/usb/usbaudio.c

diff --combined sound/core/pcm_native.c
index 17935746eb1806c43d7e0dd147bbbcbd7be0f6fa,f7e1c9f0d3ed6b969892e2d1161998faebdc509a..87288762403055a3f6f842c70b9e99794956a1cd
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/pm_qos_params.h>
  #include <linux/uio.h>
  #include <linux/dma-mapping.h>
 +#include <linux/math64.h>
  #include <sound/core.h>
  #include <sound/control.h>
  #include <sound/info.h>
@@@ -316,10 -315,10 +316,10 @@@ int snd_pcm_hw_refine(struct snd_pcm_su
        if (!params->info)
                params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
        if (!params->fifo_size) {
-               if (snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) ==
-                   snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) &&
-                     snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) ==
-                     snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) {
+               m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+               i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+               if (snd_mask_min(m) == snd_mask_max(m) &&
+                     snd_interval_min(i) == snd_interval_max(i)) {
                        changed = substream->ops->ioctl(substream,
                                        SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
                        if (changed < 0)
@@@ -367,38 -366,6 +367,38 @@@ static int period_to_usecs(struct snd_p
        return usecs;
  }
  
 +static int calc_boundary(struct snd_pcm_runtime *runtime)
 +{
 +      u_int64_t boundary;
 +
 +      boundary = (u_int64_t)runtime->buffer_size *
 +                 (u_int64_t)runtime->period_size;
 +#if BITS_PER_LONG < 64
 +      /* try to find lowest common multiple for buffer and period */
 +      if (boundary > LONG_MAX - runtime->buffer_size) {
 +              u_int32_t remainder = -1;
 +              u_int32_t divident = runtime->buffer_size;
 +              u_int32_t divisor = runtime->period_size;
 +              while (remainder) {
 +                      remainder = divident % divisor;
 +                      if (remainder) {
 +                              divident = divisor;
 +                              divisor = remainder;
 +                      }
 +              }
 +              boundary = div_u64(boundary, divisor);
 +              if (boundary > LONG_MAX - runtime->buffer_size)
 +                      return -ERANGE;
 +      }
 +#endif
 +      if (boundary == 0)
 +              return -ERANGE;
 +      runtime->boundary = boundary;
 +      while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
 +              runtime->boundary *= 2;
 +      return 0;
 +}
 +
  static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
  {
        runtime->stop_threshold = runtime->buffer_size;
        runtime->silence_threshold = 0;
        runtime->silence_size = 0;
 -      runtime->boundary = runtime->buffer_size;
 -      while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
 -              runtime->boundary *= 2;
 +      err = calc_boundary(runtime);
 +      if (err < 0)
 +              goto _error;
  
        snd_pcm_timer_resolution_change(substream);
        runtime->status->state = SNDRV_PCM_STATE_SETUP;
@@@ -549,7 -516,6 +549,7 @@@ static int snd_pcm_sw_params(struct snd
                             struct snd_pcm_sw_params *params)
  {
        struct snd_pcm_runtime *runtime;
 +      int err;
  
        if (PCM_RUNTIME_CHECK(substream))
                return -ENXIO;
                if (params->silence_threshold > runtime->buffer_size)
                        return -EINVAL;
        }
 +      err = 0;
        snd_pcm_stream_lock_irq(substream);
        runtime->tstamp_mode = params->tstamp_mode;
        runtime->period_step = params->period_step;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
                    runtime->silence_size > 0)
                        snd_pcm_playback_silence(substream, ULONG_MAX);
 -              wake_up(&runtime->sleep);
 +              err = snd_pcm_update_state(substream, runtime);
        }
        snd_pcm_stream_unlock_irq(substream);
 -      return 0;
 +      return err;
  }
  
  static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
@@@ -952,7 -917,6 +952,7 @@@ static void snd_pcm_post_stop(struct sn
                runtime->status->state = state;
        }
        wake_up(&runtime->sleep);
 +      wake_up(&runtime->tsleep);
  }
  
  static struct action_ops snd_pcm_action_stop = {
@@@ -1038,7 -1002,6 +1038,7 @@@ static void snd_pcm_post_pause(struct s
                                         SNDRV_TIMER_EVENT_MPAUSE,
                                         &runtime->trigger_tstamp);
                wake_up(&runtime->sleep);
 +              wake_up(&runtime->tsleep);
        } else {
                runtime->status->state = SNDRV_PCM_STATE_RUNNING;
                if (substream->timer)
@@@ -1096,7 -1059,6 +1096,7 @@@ static void snd_pcm_post_suspend(struc
        runtime->status->suspended_state = runtime->status->state;
        runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
        wake_up(&runtime->sleep);
 +      wake_up(&runtime->tsleep);
  }
  
  static struct action_ops snd_pcm_action_suspend = {
@@@ -3200,7 -3162,9 +3200,7 @@@ int snd_pcm_lib_mmap_iomem(struct snd_p
        long size;
        unsigned long offset;
  
 -#ifdef pgprot_noncached
        area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
 -#endif
        area->vm_flags |= VM_IO;
        size = area->vm_end - area->vm_start;
        offset = area->vm_pgoff << PAGE_SHIFT;
  EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
  #endif /* SNDRV_PCM_INFO_MMAP */
  
 +/* mmap callback with pgprot_noncached */
 +int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
 +                             struct vm_area_struct *area)
 +{
 +      area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
 +      return snd_pcm_default_mmap(substream, area);
 +}
 +EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
 +
  /*
   * mmap DMA buffer
   */
diff --combined sound/pci/atiixp.c
index 81e2bfc11257b93d123cab3afb5f96b953a28109,42b4fbbd8e2b196b47c967d4057a634fe004b602..49d572a7b235cd21dfc8a3f5d8069b728a9ec2dc
@@@ -286,7 -286,7 +286,7 @@@ struct atiixp 
  
  /*
   */
 -static struct pci_device_id snd_atiixp_ids[] = {
 +static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = {
        { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */
        { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */
        { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */
  MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
  
  static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
+       SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
        SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
        { } /* terminator */
  };
index 2783ce6c236e422d23d3b18fced58d67aede3c8e,641d7f07392c63edea8bcf8a9bc71957914239cd..8dab82d7d19d1368abdcb26dd25b7ae581a058b2
@@@ -36,61 -36,22 +36,61 @@@ MODULE_PARM_DESC(enable, "Enable " ECHO
  static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
  static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1);
  
 +
 +
  static int get_firmware(const struct firmware **fw_entry,
 -                      const struct firmware *frm, struct echoaudio *chip)
 +                      struct echoaudio *chip, const short fw_index)
  {
        int err;
        char name[30];
 -      DE_ACT(("firmware requested: %s\n", frm->data));
 -      snprintf(name, sizeof(name), "ea/%s", frm->data);
 -      if ((err = request_firmware(fw_entry, name, pci_device(chip))) < 0)
 +
 +#ifdef CONFIG_PM
 +      if (chip->fw_cache[fw_index]) {
 +              DE_ACT(("firmware requested: %s is cached\n", card_fw[fw_index].data));
 +              *fw_entry = chip->fw_cache[fw_index];
 +              return 0;
 +      }
 +#endif
 +
 +      DE_ACT(("firmware requested: %s\n", card_fw[fw_index].data));
 +      snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data);
 +      err = request_firmware(fw_entry, name, pci_device(chip));
 +      if (err < 0)
                snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err);
 +#ifdef CONFIG_PM
 +      else
 +              chip->fw_cache[fw_index] = *fw_entry;
 +#endif
        return err;
  }
  
 +
 +
  static void free_firmware(const struct firmware *fw_entry)
  {
 +#ifdef CONFIG_PM
 +      DE_ACT(("firmware not released (kept in cache)\n"));
 +#else
        release_firmware(fw_entry);
        DE_ACT(("firmware released\n"));
 +#endif
 +}
 +
 +
 +
 +static void free_firmware_cache(struct echoaudio *chip)
 +{
 +#ifdef CONFIG_PM
 +      int i;
 +
 +      for (i = 0; i < 8 ; i++)
 +              if (chip->fw_cache[i]) {
 +                      release_firmware(chip->fw_cache[i]);
 +                      DE_ACT(("release_firmware(%d)\n", i));
 +              }
 +
 +      DE_ACT(("firmware_cache released\n"));
 +#endif
  }
  
  
@@@ -753,8 -714,6 +753,8 @@@ static int pcm_trigger(struct snd_pcm_s
  
        spin_lock(&chip->lock);
        switch (cmd) {
 +      case SNDRV_PCM_TRIGGER_RESUME:
 +              DE_ACT(("pcm_trigger resume\n"));
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                DE_ACT(("pcm_trigger start\n"));
                err = start_transport(chip, channelmask,
                                      chip->pipe_cyclic_mask);
                break;
 +      case SNDRV_PCM_TRIGGER_SUSPEND:
 +              DE_ACT(("pcm_trigger suspend\n"));
        case SNDRV_PCM_TRIGGER_STOP:
                DE_ACT(("pcm_trigger stop\n"));
                for (i = 0; i < DSP_MAXPIPES; i++) {
@@@ -1864,7 -1821,9 +1864,9 @@@ static irqreturn_t snd_echo_interrupt(i
        /* The hardware doesn't tell us which substream caused the irq,
        thus we have to check all running substreams. */
        for (ss = 0; ss < DSP_MAXPIPES; ss++) {
-               if ((substream = chip->substream[ss])) {
+               substream = chip->substream[ss];
+               if (substream && ((struct audiopipe *)substream->runtime->
+                               private_data)->state == PIPE_STATE_STARTED) {
                        period = pcm_pointer(substream) /
                                substream->runtime->period_size;
                        if (period != chip->last_period[ss]) {
@@@ -1917,7 -1876,6 +1919,7 @@@ static int snd_echo_free(struct echoaud
        pci_disable_device(chip->pci);
  
        /* release chip data */
 +      free_firmware_cache(chip);
        kfree(chip);
        DE_INIT(("Chip freed.\n"));
        return 0;
@@@ -1955,27 -1913,18 +1957,27 @@@ static __devinit int snd_echo_create(st
                return err;
        pci_set_master(pci);
  
 -      /* allocate a chip-specific data */
 -      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 -      if (!chip) {
 -              pci_disable_device(pci);
 -              return -ENOMEM;
 +      /* Allocate chip if needed */
 +      if (!*rchip) {
 +              chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 +              if (!chip) {
 +                      pci_disable_device(pci);
 +                      return -ENOMEM;
 +              }
 +              DE_INIT(("chip=%p\n", chip));
 +              spin_lock_init(&chip->lock);
 +              chip->card = card;
 +              chip->pci = pci;
 +              chip->irq = -1;
 +              atomic_set(&chip->opencount, 0);
 +              mutex_init(&chip->mode_mutex);
 +              chip->can_set_rate = 1;
 +      } else {
 +              /* If this was called from the resume function, chip is
 +               * already allocated and it contains current card settings.
 +               */
 +              chip = *rchip;
        }
 -      DE_INIT(("chip=%p\n", chip));
 -
 -      spin_lock_init(&chip->lock);
 -      chip->card = card;
 -      chip->pci = pci;
 -      chip->irq = -1;
  
        /* PCI resource allocation */
        chip->dsp_registers_phys = pci_resource_start(pci, 0);
        chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
  
        err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
 -      if (err) {
 +      if (err >= 0)
 +              err = set_mixer_defaults(chip);
 +      if (err < 0) {
                DE_INIT(("init_hw err=%d\n", err));
                snd_echo_free(chip);
                return err;
                snd_echo_free(chip);
                return err;
        }
 -      atomic_set(&chip->opencount, 0);
 -      mutex_init(&chip->mode_mutex);
 -      chip->can_set_rate = 1;
        *rchip = chip;
        /* Init done ! */
        return 0;
@@@ -2060,7 -2010,6 +2062,7 @@@ static int __devinit snd_echo_probe(str
  
        snd_card_set_dev(card, &pci->dev);
  
 +      chip = NULL;    /* Tells snd_echo_create to allocate chip */
        if ((err = snd_echo_create(card, pci, &chip)) < 0) {
                snd_card_free(card);
                return err;
@@@ -2200,112 -2149,6 +2202,112 @@@ ctl_error
  
  
  
 +#if defined(CONFIG_PM)
 +
 +static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state)
 +{
 +      struct echoaudio *chip = pci_get_drvdata(pci);
 +
 +      DE_INIT(("suspend start\n"));
 +      snd_pcm_suspend_all(chip->analog_pcm);
 +      snd_pcm_suspend_all(chip->digital_pcm);
 +
 +#ifdef ECHOCARD_HAS_MIDI
 +      /* This call can sleep */
 +      if (chip->midi_out)
 +              snd_echo_midi_output_trigger(chip->midi_out, 0);
 +#endif
 +      spin_lock_irq(&chip->lock);
 +      if (wait_handshake(chip)) {
 +              spin_unlock_irq(&chip->lock);
 +              return -EIO;
 +      }
 +      clear_handshake(chip);
 +      if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) {
 +              spin_unlock_irq(&chip->lock);
 +              return -EIO;
 +      }
 +      spin_unlock_irq(&chip->lock);
 +
 +      chip->dsp_code = NULL;
 +      free_irq(chip->irq, chip);
 +      chip->irq = -1;
 +      pci_save_state(pci);
 +      pci_disable_device(pci);
 +
 +      DE_INIT(("suspend done\n"));
 +      return 0;
 +}
 +
 +
 +
 +static int snd_echo_resume(struct pci_dev *pci)
 +{
 +      struct echoaudio *chip = pci_get_drvdata(pci);
 +      struct comm_page *commpage, *commpage_bak;
 +      u32 pipe_alloc_mask;
 +      int err;
 +
 +      DE_INIT(("resume start\n"));
 +      pci_restore_state(pci);
 +      commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
 +      commpage = chip->comm_page;
 +      memcpy(commpage_bak, commpage, sizeof(struct comm_page));
 +
 +      err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
 +      if (err < 0) {
 +              kfree(commpage_bak);
 +              DE_INIT(("resume init_hw err=%d\n", err));
 +              snd_echo_free(chip);
 +              return err;
 +      }
 +      DE_INIT(("resume init OK\n"));
 +
 +      /* Temporarily set chip->pipe_alloc_mask=0 otherwise
 +       * restore_dsp_settings() fails.
 +       */
 +      pipe_alloc_mask = chip->pipe_alloc_mask;
 +      chip->pipe_alloc_mask = 0;
 +      err = restore_dsp_rettings(chip);
 +      chip->pipe_alloc_mask = pipe_alloc_mask;
 +      if (err < 0) {
 +              kfree(commpage_bak);
 +              return err;
 +      }
 +      DE_INIT(("resume restore OK\n"));
 +
 +      memcpy(&commpage->audio_format, &commpage_bak->audio_format,
 +              sizeof(commpage->audio_format));
 +      memcpy(&commpage->sglist_addr, &commpage_bak->sglist_addr,
 +              sizeof(commpage->sglist_addr));
 +      memcpy(&commpage->midi_output, &commpage_bak->midi_output,
 +              sizeof(commpage->midi_output));
 +      kfree(commpage_bak);
 +
 +      if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
 +                      ECHOCARD_NAME, chip)) {
 +              snd_echo_free(chip);
 +              snd_printk(KERN_ERR "cannot grab irq\n");
 +              return -EBUSY;
 +      }
 +      chip->irq = pci->irq;
 +      DE_INIT(("resume irq=%d\n", chip->irq));
 +
 +#ifdef ECHOCARD_HAS_MIDI
 +      if (chip->midi_input_enabled)
 +              enable_midi_input(chip, TRUE);
 +      if (chip->midi_out)
 +              snd_echo_midi_output_trigger(chip->midi_out, 1);
 +#endif
 +
 +      DE_INIT(("resume done\n"));
 +      return 0;
 +}
 +
 +#endif /* CONFIG_PM */
 +
 +
 +
  static void __devexit snd_echo_remove(struct pci_dev *pci)
  {
        struct echoaudio *chip;
@@@ -2328,10 -2171,6 +2330,10 @@@ static struct pci_driver driver = 
        .id_table = snd_echo_ids,
        .probe = snd_echo_probe,
        .remove = __devexit_p(snd_echo_remove),
 +#ifdef CONFIG_PM
 +      .suspend = snd_echo_suspend,
 +      .resume = snd_echo_resume,
 +#endif /* CONFIG_PM */
  };
  
  
index ac05bef7c2ec1177942d82ddabb62d4cf02cc3d2,3600e9cc9bc604ce61a1b11871424a40c7b5c5a3..8d8e0b5aa2486e7a430172fc5c9020bd964347e9
@@@ -426,6 -426,7 +426,7 @@@ struct azx 
  
        /* flags */
        int position_fix;
+       int poll_count;
        unsigned int running :1;
        unsigned int initialized :1;
        unsigned int single_cmd :1;
@@@ -506,7 -507,7 +507,7 @@@ static char *driver_short_names[] __dev
  #define get_azx_dev(substream) (substream->runtime->private_data)
  
  static int azx_acquire_irq(struct azx *chip, int do_disconnect);
+ static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
  /*
   * Interface for HD codec
   */
@@@ -664,11 -665,12 +665,12 @@@ static unsigned int azx_rirb_get_respon
  {
        struct azx *chip = bus->private_data;
        unsigned long timeout;
+       int do_poll = 0;
  
   again:
        timeout = jiffies + msecs_to_jiffies(1000);
        for (;;) {
-               if (chip->polling_mode) {
+               if (chip->polling_mode || do_poll) {
                        spin_lock_irq(&chip->reg_lock);
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                if (!chip->rirb.cmds[addr]) {
                        smp_rmb();
                        bus->rirb_error = 0;
+                       if (!do_poll)
+                               chip->poll_count = 0;
                        return chip->rirb.res[addr]; /* the last value */
                }
                if (time_after(jiffies, timeout))
                }
        }
  
+       if (!chip->polling_mode && chip->poll_count < 2) {
+               snd_printdd(SFX "azx_get_response timeout, "
+                          "polling the codec once: last cmd=0x%08x\n",
+                          chip->last_cmd[addr]);
+               do_poll = 1;
+               chip->poll_count++;
+               goto again;
+       }
        if (!chip->polling_mode) {
                snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
                           "switching to polling mode: last cmd=0x%08x\n",
@@@ -1878,6 -1893,9 +1893,9 @@@ static int azx_position_ok(struct azx *
  
        if (!bdl_pos_adj[chip->dev_index])
                return 1; /* no delayed ack */
+       if (WARN_ONCE(!azx_dev->period_bytes,
+                     "hda-intel: zero azx_dev->period_bytes"))
+               return 0; /* this shouldn't happen! */
        if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
                return 0; /* NG - it's below the period boundary */
        return 1; /* OK, it's fine */
@@@ -2043,7 -2061,7 +2061,7 @@@ static int azx_acquire_irq(struct azx *
  {
        if (request_irq(chip->pci->irq, azx_interrupt,
                        chip->msi ? 0 : IRQF_SHARED,
-                       "HDA Intel", chip)) {
+                       "hda_intel", chip)) {
                printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
                       "disabling device\n", chip->pci->irq);
                if (do_disconnect)
@@@ -2332,6 -2350,7 +2350,7 @@@ static void __devinit check_probe_mask(
   */
  static struct snd_pci_quirk msi_black_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
+       SND_PCI_QUIRK(0x1043, 0x829c, "ASUS", 0), /* nvidia */
        {}
  };
  
@@@ -2664,7 -2683,7 +2683,7 @@@ static void __devexit azx_remove(struc
  }
  
  /* PCI IDs */
 -static struct pci_device_id azx_ids[] = {
 +static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* ICH 6..10 */
        { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
        /* ULI M5461 */
        { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
        /* NVIDIA MCP */
 -      { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
 +      { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
 +        .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
 +        .class_mask = 0xffffff,
 +        .driver_data = AZX_DRIVER_NVIDIA },
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
        /* Creative X-Fi (CA0110-IBG) */
index 141ff446104ab30b169727681ced2368f72172a5,da34095c707fd7b19fb33156248fc6461a7090e0..f628c33d80b3269830b184d9f1b883b7decbe322
@@@ -338,7 -338,7 +338,7 @@@ struct alc_spec 
        void (*init_hook)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 -      void (*power_hook)(struct hda_codec *codec, int power);
 +      void (*power_hook)(struct hda_codec *codec);
  #endif
  
        /* for pin sensing */
@@@ -391,7 -391,7 +391,7 @@@ struct alc_config_preset 
        void (*init_hook)(struct hda_codec *);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_amp_list *loopbacks;
 -      void (*power_hook)(struct hda_codec *codec, int power);
 +      void (*power_hook)(struct hda_codec *codec);
  #endif
  };
  
@@@ -633,7 -633,6 +633,7 @@@ static int alc_pin_mode_put(struct snd_
  
  #define ALC_PIN_MODE(xname, nid, dir) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_pin_mode_info, \
          .get = alc_pin_mode_get, \
          .put = alc_pin_mode_put, \
@@@ -685,7 -684,6 +685,7 @@@ static int alc_gpio_data_put(struct snd
  }
  #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_gpio_data_info, \
          .get = alc_gpio_data_get, \
          .put = alc_gpio_data_put, \
@@@ -740,7 -738,6 +740,7 @@@ static int alc_spdif_ctrl_put(struct sn
  }
  #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_spdif_ctrl_info, \
          .get = alc_spdif_ctrl_get, \
          .put = alc_spdif_ctrl_put, \
@@@ -794,7 -791,6 +794,7 @@@ static int alc_eapd_ctrl_put(struct snd
  
  #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_eapd_ctrl_info, \
          .get = alc_eapd_ctrl_get, \
          .put = alc_eapd_ctrl_put, \
@@@ -1097,6 -1093,16 +1097,16 @@@ static void alc889_coef_init(struct hda
        snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
  }
  
+ /* turn on/off EAPD control (only if available) */
+ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
+ {
+       if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
+               return;
+       if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
+                                   on ? 2 : 0);
+ }
  static void alc_auto_init_amp(struct hda_codec *codec, int type)
  {
        unsigned int tmp;
        case ALC_INIT_DEFAULT:
                switch (codec->vendor_id) {
                case 0x10ec0260:
-                       snd_hda_codec_write(codec, 0x0f, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
-                       snd_hda_codec_write(codec, 0x10, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
+                       set_eapd(codec, 0x0f, 1);
+                       set_eapd(codec, 0x10, 1);
                        break;
                case 0x10ec0262:
                case 0x10ec0267:
                case 0x10ec0268:
                case 0x10ec0269:
+               case 0x10ec0270:
                case 0x10ec0272:
                case 0x10ec0660:
                case 0x10ec0662:
                case 0x10ec0663:
                case 0x10ec0862:
                case 0x10ec0889:
-                       snd_hda_codec_write(codec, 0x14, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
-                       snd_hda_codec_write(codec, 0x15, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
+                       set_eapd(codec, 0x14, 1);
+                       set_eapd(codec, 0x15, 1);
                        break;
                }
                switch (codec->vendor_id) {
@@@ -1234,6 -1237,8 +1241,8 @@@ static void alc_init_auto_mic(struct hd
                        return; /* invalid entry */
                }
        }
+       if (!ext || !fixed)
+               return;
        if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
                return; /* no unsol support */
        snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
@@@ -1835,6 -1840,14 +1844,6 @@@ static void alc889_acer_aspire_8930g_se
        spec->autocfg.speaker_pins[2] = 0x1b;
  }
  
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -static void alc889_power_eapd(struct hda_codec *codec, int power)
 -{
 -      set_eapd(codec, 0x14, power);
 -      set_eapd(codec, 0x15, power);
 -}
 -#endif
 -
  /*
   * ALC880 3-stack model
   *
@@@ -2437,15 -2450,6 +2446,15 @@@ static const char *alc_slave_sws[] = 
   * build control elements
   */
  
 +#define NID_MAPPING           (-1)
 +
 +#define SUBDEV_SPEAKER_               (0 << 6)
 +#define SUBDEV_HP_            (1 << 6)
 +#define SUBDEV_LINE_          (2 << 6)
 +#define SUBDEV_SPEAKER(x)     (SUBDEV_SPEAKER_ | ((x) & 0x3f))
 +#define SUBDEV_HP(x)          (SUBDEV_HP_ | ((x) & 0x3f))
 +#define SUBDEV_LINE(x)                (SUBDEV_LINE_ | ((x) & 0x3f))
 +
  static void alc_free_kctls(struct hda_codec *codec);
  
  #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@@ -2460,11 -2464,8 +2469,11 @@@ static struct snd_kcontrol_new alc_beep
  static int alc_build_controls(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      int err;
 -      int i;
 +      struct snd_kcontrol *kctl;
 +      struct snd_kcontrol_new *knew;
 +      int i, j, err;
 +      unsigned int u;
 +      hda_nid_t nid;
  
        for (i = 0; i < spec->num_mixers; i++) {
                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
                        if (!kctl)
                                return -ENOMEM;
                        kctl->private_value = spec->beep_amp;
 -                      err = snd_hda_ctl_add(codec,
 -                                      get_amp_nid_(spec->beep_amp), kctl);
 +                      err = snd_hda_ctl_add(codec, 0, kctl);
                        if (err < 0)
                                return err;
                }
        }
  
        alc_free_kctls(codec); /* no longer needed */
 +
 +      /* assign Capture Source enums to NID */
 +      kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
 +      if (!kctl)
 +              kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 +      for (i = 0; kctl && i < kctl->count; i++) {
 +              hda_nid_t *nids = spec->capsrc_nids;
 +              if (!nids)
 +                      nids = spec->adc_nids;
 +              err = snd_hda_add_nid(codec, kctl, i, nids[i]);
 +              if (err < 0)
 +                      return err;
 +      }
 +      if (spec->cap_mixer) {
 +              const char *kname = kctl ? kctl->id.name : NULL;
 +              for (knew = spec->cap_mixer; knew->name; knew++) {
 +                      if (kname && strcmp(knew->name, kname) == 0)
 +                              continue;
 +                      kctl = snd_hda_find_mixer_ctl(codec, knew->name);
 +                      for (i = 0; kctl && i < kctl->count; i++) {
 +                              err = snd_hda_add_nid(codec, kctl, i,
 +                                                    spec->adc_nids[i]);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +              }
 +      }
 +
 +      /* other nid->control mapping */
 +      for (i = 0; i < spec->num_mixers; i++) {
 +              for (knew = spec->mixers[i]; knew->name; knew++) {
 +                      if (knew->iface != NID_MAPPING)
 +                              continue;
 +                      kctl = snd_hda_find_mixer_ctl(codec, knew->name);
 +                      if (kctl == NULL)
 +                              continue;
 +                      u = knew->subdevice;
 +                      for (j = 0; j < 4; j++, u >>= 8) {
 +                              nid = u & 0x3f;
 +                              if (nid == 0)
 +                                      continue;
 +                              switch (u & 0xc0) {
 +                              case SUBDEV_SPEAKER_:
 +                                      nid = spec->autocfg.speaker_pins[nid];
 +                                      break;
 +                              case SUBDEV_LINE_:
 +                                      nid = spec->autocfg.line_out_pins[nid];
 +                                      break;
 +                              case SUBDEV_HP_:
 +                                      nid = spec->autocfg.hp_pins[nid];
 +                                      break;
 +                              default:
 +                                      continue;
 +                              }
 +                              err = snd_hda_add_nid(codec, kctl, 0, nid);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +                      u = knew->private_value;
 +                      for (j = 0; j < 4; j++, u >>= 8) {
 +                              nid = u & 0xff;
 +                              if (nid == 0)
 +                                      continue;
 +                              err = snd_hda_add_nid(codec, kctl, 0, nid);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +              }
 +      }
        return 0;
  }
  
@@@ -3683,11 -3616,6 +3692,11 @@@ static int alc_build_pcms(struct hda_co
        return 0;
  }
  
 +static inline void alc_shutup(struct hda_codec *codec)
 +{
 +      snd_hda_shutup_pins(codec);
 +}
 +
  static void alc_free_kctls(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
@@@ -3708,47 -3636,17 +3717,47 @@@ static void alc_free(struct hda_codec *
        if (!spec)
                return;
  
 +      alc_shutup(codec);
        alc_free_kctls(codec);
        kfree(spec);
        snd_hda_detach_beep_device(codec);
  }
  
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 +static void alc_power_eapd(struct hda_codec *codec)
 +{
 +      /* We currently only handle front, HP */
 +      switch (codec->vendor_id) {
 +      case 0x10ec0260:
 +              snd_hda_codec_write(codec, 0x0f, 0,
 +                                  AC_VERB_SET_EAPD_BTLENABLE, 0x00);
 +              snd_hda_codec_write(codec, 0x10, 0,
 +                                  AC_VERB_SET_EAPD_BTLENABLE, 0x00);
 +              break;
 +      case 0x10ec0262:
 +      case 0x10ec0267:
 +      case 0x10ec0268:
 +      case 0x10ec0269:
 +      case 0x10ec0272:
 +      case 0x10ec0660:
 +      case 0x10ec0662:
 +      case 0x10ec0663:
 +      case 0x10ec0862:
 +      case 0x10ec0889:
 +              snd_hda_codec_write(codec, 0x14, 0,
 +                                  AC_VERB_SET_EAPD_BTLENABLE, 0x00);
 +              snd_hda_codec_write(codec, 0x15, 0,
 +                                  AC_VERB_SET_EAPD_BTLENABLE, 0x00);
 +              break;
 +      }
 +}
 +
  static int alc_suspend(struct hda_codec *codec, pm_message_t state)
  {
        struct alc_spec *spec = codec->spec;
 +      alc_shutup(codec);
        if (spec && spec->power_hook)
 -              spec->power_hook(codec, 0);
 +              spec->power_hook(codec);
        return 0;
  }
  #endif
  #ifdef SND_HDA_NEEDS_RESUME
  static int alc_resume(struct hda_codec *codec)
  {
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -      struct alc_spec *spec = codec->spec;
 -#endif
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -      if (spec && spec->power_hook)
 -              spec->power_hook(codec, 1);
 -#endif
        return 0;
  }
  #endif
@@@ -3778,7 -3683,6 +3787,7 @@@ static struct hda_codec_ops alc_patch_o
        .suspend = alc_suspend,
        .check_power_status = alc_check_power_status,
  #endif
 +      .reboot_notify = alc_shutup,
  };
  
  
@@@ -3935,7 -3839,6 +3944,7 @@@ static int alc_test_pin_src_put(struct 
  #define PIN_CTL_TEST(xname,nid) {                     \
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
                        .name = xname,                 \
 +                      .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
                        .info = alc_test_pin_ctl_info, \
                        .get = alc_test_pin_ctl_get,   \
                        .put = alc_test_pin_ctl_put,   \
  #define PIN_SRC_TEST(xname,nid) {                     \
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
                        .name = xname,                 \
 +                      .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
                        .info = alc_test_pin_src_info, \
                        .get = alc_test_pin_src_get,   \
                        .put = alc_test_pin_src_put,   \
@@@ -4485,7 -4387,7 +4494,7 @@@ static int add_control(struct alc_spec 
        if (!knew->name)
                return -ENOMEM;
        if (get_amp_nid_(val))
 -              knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
 +              knew->subdevice = HDA_SUBDEV_AMP_FLAG;
        knew->private_value = val;
        return 0;
  }
@@@ -4917,6 -4819,49 +4926,49 @@@ static void fixup_automic_adc(struct hd
        spec->auto_mic = 0; /* disable auto-mic to be sure */
  }
  
+ /* choose the ADC/MUX containing the input pin and initialize the setup */
+ static void fixup_single_adc(struct hda_codec *codec)
+ {
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t pin;
+       int i;
+       /* search for the input pin; there must be only one */
+       for (i = 0; i < AUTO_PIN_LAST; i++) {
+               if (spec->autocfg.input_pins[i]) {
+                       pin = spec->autocfg.input_pins[i];
+                       break;
+               }
+       }
+       if (!pin)
+               return;
+       /* set the default connection to that pin */
+       for (i = 0; i < spec->num_adc_nids; i++) {
+               hda_nid_t cap = spec->capsrc_nids ?
+                       spec->capsrc_nids[i] : spec->adc_nids[i];
+               int idx;
+               idx = get_connection_index(codec, cap, pin);
+               if (idx < 0)
+                       continue;
+               /* use only this ADC */
+               if (spec->capsrc_nids)
+                       spec->capsrc_nids += i;
+               spec->adc_nids += i;
+               spec->num_adc_nids = 1;
+               /* select or unmute this route */
+               if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
+                       snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
+                                                HDA_AMP_MUTE, 0);
+               } else {
+                       snd_hda_codec_write_cache(codec, cap, 0,
+                                         AC_VERB_SET_CONNECT_SEL, idx);
+               }
+               return;
+       }
+ }
  static void set_capture_mixer(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
                  alc_capture_mixer3 },
        };
        if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
-               int mux;
-               if (spec->auto_mic) {
-                       mux = 0;
+               int mux = 0;
+               if (spec->auto_mic)
                        fixup_automic_adc(codec);
-               } else if (spec->input_mux && spec->input_mux->num_items > 1)
-                       mux = 1;
-               else
-                       mux = 0;
+               else if (spec->input_mux) {
+                       if (spec->input_mux->num_items > 1)
+                               mux = 1;
+                       else if (spec->input_mux->num_items == 1)
+                               fixup_single_adc(codec);
+               }
                spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
        }
  }
@@@ -5236,7 -5182,6 +5289,7 @@@ static struct snd_kcontrol_new alc260_h
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
                .info = snd_ctl_boolean_mono_info,
                .get = alc260_hp_master_sw_get,
                .put = alc260_hp_master_sw_put,
@@@ -5275,7 -5220,6 +5328,7 @@@ static struct snd_kcontrol_new alc260_h
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
                .info = snd_ctl_boolean_mono_info,
                .get = alc260_hp_master_sw_get,
                .put = alc260_hp_master_sw_put,
@@@ -7201,8 -7145,8 +7254,8 @@@ static struct snd_kcontrol_new alc885_m
        HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
        HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-       HDA_BIND_MUTE   ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+       HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@@ -7603,6 -7547,7 +7656,7 @@@ static struct hda_verb alc885_mb5_init_
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+       {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
        /* Front Mic pin: input vref at 80% */
        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@@ -7787,6 -7732,27 +7841,27 @@@ static void alc885_mbp3_setup(struct hd
        spec->autocfg.speaker_pins[0] = 0x14;
  }
  
+ static void alc885_mb5_automute(struct hda_codec *codec)
+ {
+       unsigned int present;
+       present = snd_hda_codec_read(codec, 0x14, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+       snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ }
+ static void alc885_mb5_unsol_event(struct hda_codec *codec,
+                                   unsigned int res)
+ {
+       /* Headphone insertion or removal. */
+       if ((res >> 26) == ALC880_HP_EVENT)
+               alc885_mb5_automute(codec);
+ }
  static void alc885_imac91_automute(struct hda_codec *codec)
  {
        unsigned int present;
@@@ -9233,6 -9199,8 +9308,8 @@@ static struct alc_config_preset alc882_
                .input_mux = &mb5_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
+               .unsol_event = alc885_mb5_unsol_event,
+               .init_hook = alc885_mb5_automute,
        },
        [ALC885_MACPRO] = {
                .mixers = { alc882_macpro_mixer },
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
+               .const_channel_count = 6,
                .num_mux_defs =
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_2_capture_sources,
                .setup = alc889_acer_aspire_8930g_setup,
                .init_hook = alc_automute_amp,
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 -              .power_hook = alc889_power_eapd,
 +              .power_hook = alc_power_eapd,
  #endif
        },
        [ALC888_ACER_ASPIRE_7730G] = {
@@@ -10355,14 -10324,8 +10433,14 @@@ static int alc262_hp_master_sw_put(stru
                .info = snd_ctl_boolean_mono_info,              \
                .get = alc262_hp_master_sw_get,                 \
                .put = alc262_hp_master_sw_put,                 \
 +      }, \
 +      {                                                       \
 +              .iface = NID_MAPPING,                           \
 +              .name = "Master Playback Switch",               \
 +              .private_value = 0x15 | (0x16 << 8) | (0x1b << 16),     \
        }
  
 +
  static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
        ALC262_HP_MASTER_SWITCH,
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@@ -10420,7 -10383,7 +10498,7 @@@ static void alc262_hp_t5735_setup(struc
        struct alc_spec *spec = codec->spec;
  
        spec->autocfg.hp_pins[0] = 0x15;
-       spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */
+       spec->autocfg.speaker_pins[0] = 0x14;
  }
  
  static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@@ -10520,12 -10483,6 +10598,12 @@@ static int alc262_hippo_master_sw_put(s
                .info = snd_ctl_boolean_mono_info,              \
                .get = alc262_hippo_master_sw_get,              \
                .put = alc262_hippo_master_sw_put,              \
 +      },                                                      \
 +      {                                                       \
 +              .iface = NID_MAPPING,                           \
 +              .name = "Master Playback Switch",               \
 +              .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
 +                           (SUBDEV_SPEAKER(0) << 16), \
        }
  
  static struct snd_kcontrol_new alc262_hippo_mixer[] = {
@@@ -11006,17 -10963,11 +11084,17 @@@ static struct snd_kcontrol_new alc262_f
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc262_fujitsu_master_sw_put,
                .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
        },
 +      {
 +              .iface = NID_MAPPING,
 +              .name = "Master Playback Switch",
 +              .private_value = 0x1b,
 +      },
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
@@@ -11047,7 -10998,6 +11125,7 @@@ static struct snd_kcontrol_new alc262_l
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc262_lenovo_3000_master_sw_put,
@@@ -11202,11 -11152,6 +11280,11 @@@ static struct snd_kcontrol_new alc262_u
                .get = alc_mux_enum_get,
                .put = alc262_ultra_mux_enum_put,
        },
 +      {
 +              .iface = NID_MAPPING,
 +              .name = "Capture Source",
 +              .private_value = 0x15,
 +      },
        { } /* end */
  };
  
@@@ -11310,7 -11255,7 +11388,7 @@@ static int alc262_auto_create_multi_out
  }
  
  #define alc262_auto_create_input_ctls \
-       alc880_auto_create_input_ctls
+       alc882_auto_create_input_ctls
  
  /*
   * generic initialization of ADC, input mixers and output mixers
@@@ -11849,9 -11794,9 +11927,9 @@@ static struct alc_config_preset alc262_
                .num_channel_mode = ARRAY_SIZE(alc262_modes),
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc262_hp_t5735_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_inithook,
        },
        [ALC262_HP_RP5700] = {
                .mixers = { alc262_hp_rp5700_mixer },
@@@ -12225,7 -12170,6 +12303,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12241,7 -12185,6 +12319,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12259,7 -12202,6 +12337,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12605,6 -12547,7 +12683,7 @@@ static int alc268_new_analog_output(str
                dac = 0x02;
                break;
        case 0x15:
+       case 0x21:
                dac = 0x03;
                break;
        default:
@@@ -13212,7 -13155,6 +13291,7 @@@ static struct snd_kcontrol_new alc269_q
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -13233,7 -13175,6 +13312,7 @@@ static struct snd_kcontrol_new alc269_l
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -14991,17 -14932,15 +15070,19 @@@ static int patch_alc861(struct hda_code
        spec->stream_digital_playback = &alc861_pcm_digital_playback;
        spec->stream_digital_capture = &alc861_pcm_digital_capture;
  
+       if (!spec->cap_mixer)
+               set_capture_mixer(codec);
        set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
  
        spec->vmaster_nid = 0x03;
  
        codec->patch_ops = alc_patch_ops;
 -      if (board_config == ALC861_AUTO)
 +      if (board_config == ALC861_AUTO) {
                spec->init_hook = alc861_auto_init;
 +#ifdef CONFIG_SND_HDA_POWER_SAVE
 +              spec->power_hook = alc_power_eapd;
 +#endif
 +      }
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc861_loopbacks;
@@@ -15633,7 -15572,7 +15714,7 @@@ static struct alc_config_preset alc861v
  static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
  {
-       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
+       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0);
  }
  
  
@@@ -17391,7 -17330,7 +17472,7 @@@ static struct snd_pci_quirk alc662_cfg_
        SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
        SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
                      ALC662_3ST_6ch_DIG),
-       SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4),
+       SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
        SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
                      ALC662_3ST_6ch_DIG),
index 117919aa17f45cf812757f37d604c5d076069973,799ba2570902a066ead90e38a1ce17e5b351f4e8..dbffb5b5c69df26877ab9e28165263c659e4575b
@@@ -2688,7 -2688,7 +2688,7 @@@ static struct snd_kcontrol_new 
  stac_control_new(struct sigmatel_spec *spec,
                 struct snd_kcontrol_new *ktemp,
                 const char *name,
 -               hda_nid_t nid)
 +               unsigned int subdev)
  {
        struct snd_kcontrol_new *knew;
  
                spec->kctls.alloced--;
                return NULL;
        }
 -      if (nid)
 -              knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
 +      knew->subdevice = subdev;
        return knew;
  }
  
@@@ -2714,7 -2715,7 +2714,7 @@@ static int stac92xx_add_control_temp(st
                                     unsigned long val)
  {
        struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name,
 -                                                       get_amp_nid_(val));
 +                                                       HDA_SUBDEV_AMP_FLAG);
        if (!knew)
                return -ENOMEM;
        knew->index = idx;
@@@ -4159,52 -4160,34 +4159,52 @@@ static void stac92xx_power_down(struct 
  static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
                                  int enable);
  
 +static inline int get_int_hint(struct hda_codec *codec, const char *key,
 +                             int *valp)
 +{
 +      const char *p;
 +      p = snd_hda_get_hint(codec, key);
 +      if (p) {
 +              unsigned long val;
 +              if (!strict_strtoul(p, 0, &val)) {
 +                      *valp = val;
 +                      return 1;
 +              }
 +      }
 +      return 0;
 +}
 +
  /* override some hints from the hwdep entry */
  static void stac_store_hints(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec = codec->spec;
 -      const char *p;
        int val;
  
        val = snd_hda_get_bool_hint(codec, "hp_detect");
        if (val >= 0)
                spec->hp_detect = val;
 -      p = snd_hda_get_hint(codec, "gpio_mask");
 -      if (p) {
 -              spec->gpio_mask = simple_strtoul(p, NULL, 0);
 +      if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) {
                spec->eapd_mask = spec->gpio_dir = spec->gpio_data =
                        spec->gpio_mask;
        }
 -      p = snd_hda_get_hint(codec, "gpio_dir");
 -      if (p)
 -              spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 -      p = snd_hda_get_hint(codec, "gpio_data");
 -      if (p)
 -              spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 -      p = snd_hda_get_hint(codec, "eapd_mask");
 -      if (p)
 -              spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir))
 +              spec->gpio_mask &= spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_data", &spec->gpio_data))
 +              spec->gpio_dir &= spec->gpio_mask;
 +      if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask))
 +              spec->eapd_mask &= spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute))
 +              spec->gpio_mute &= spec->gpio_mask;
        val = snd_hda_get_bool_hint(codec, "eapd_switch");
        if (val >= 0)
                spec->eapd_switch = val;
 +      get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
 +      if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
 +              spec->gpio_mask |= spec->gpio_led;
 +              spec->gpio_dir |= spec->gpio_led;
 +              if (spec->gpio_led_polarity)
 +                      spec->gpio_data |= spec->gpio_led;
 +      }
  }
  
  static int stac92xx_init(struct hda_codec *codec)
@@@ -4389,8 -4372,18 +4389,8 @@@ static void stac92xx_free_kctls(struct 
  static void stac92xx_shutup(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec = codec->spec;
 -      int i;
 -      hda_nid_t nid;
  
 -      /* reset each pin before powering down DAC/ADC to avoid click noise */
 -      nid = codec->start_nid;
 -      for (i = 0; i < codec->num_nodes; i++, nid++) {
 -              unsigned int wcaps = get_wcaps(codec, nid);
 -              unsigned int wid_type = get_wcaps_type(wcaps);
 -              if (wid_type == AC_WID_PIN)
 -                      snd_hda_codec_read(codec, nid, 0,
 -                              AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 -      }
 +      snd_hda_shutup_pins(codec);
  
        if (spec->eapd_mask)
                stac_gpio_set(codec, spec->gpio_mask,
@@@ -4737,6 -4730,26 +4737,26 @@@ static void stac92xx_unsol_event(struc
        }
  }
  
+ static int hp_blike_system(u32 subsystem_id);
+ static void set_hp_led_gpio(struct hda_codec *codec)
+ {
+       struct sigmatel_spec *spec = codec->spec;
+       switch (codec->vendor_id) {
+       case 0x111d7608:
+               /* GPIO 0 */
+               spec->gpio_led = 0x01;
+               break;
+       case 0x111d7600:
+       case 0x111d7601:
+       case 0x111d7602:
+       case 0x111d7603:
+               /* GPIO 3 */
+               spec->gpio_led = 0x08;
+               break;
+       }
+ }
  /*
   * This method searches for the mute LED GPIO configuration
   * provided as OEM string in SMBIOS. The format of that string
   *
   * So, HP B-series like systems may have HP_Mute_LED_0 (current models)
   * or  HP_Mute_LED_0_3 (future models) OEM SMBIOS strings
+  *
+  *
+  * The dv-series laptops don't seem to have the HP_Mute_LED* strings in
+  * SMBIOS - at least the ones I have seen do not have them - which include
+  * my own system (HP Pavilion dv6-1110ax) and my cousin's
+  * HP Pavilion dv9500t CTO.
+  * Need more information on whether it is true across the entire series.
+  * -- kunal
   */
  static int find_mute_led_gpio(struct hda_codec *codec)
  {
                while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
                                                                NULL, dev))) {
                        if (sscanf(dev->name, "HP_Mute_LED_%d_%d",
-                             &spec->gpio_led_polarity,
-                             &spec->gpio_led) == 2) {
+                                 &spec->gpio_led_polarity,
+                                 &spec->gpio_led) == 2) {
                                spec->gpio_led = 1 << spec->gpio_led;
                                return 1;
                        }
                        if (sscanf(dev->name, "HP_Mute_LED_%d",
-                             &spec->gpio_led_polarity) == 1) {
-                               switch (codec->vendor_id) {
-                               case 0x111d7608:
-                                       /* GPIO 0 */
-                                       spec->gpio_led = 0x01;
-                                       return 1;
-                               case 0x111d7600:
-                               case 0x111d7601:
-                               case 0x111d7602:
-                               case 0x111d7603:
-                                       /* GPIO 3 */
-                                       spec->gpio_led = 0x08;
-                                       return 1;
-                               }
+                                 &spec->gpio_led_polarity) == 1) {
+                               set_hp_led_gpio(codec);
+                               return 1;
                        }
                }
+               /*
+                * Fallback case - if we don't find the DMI strings,
+                * we statically set the GPIO - if not a B-series system.
+                */
+               if (!hp_blike_system(codec->subsystem_id)) {
+                       set_hp_led_gpio(codec);
+                       spec->gpio_led_polarity = 1;
+                       return 1;
+               }
        }
        return 0;
  }
@@@ -5411,54 -5431,6 +5438,54 @@@ static int stac92hd71bxx_connected_smux
                return 0;
  }
  
 +/* HP dv7 bass switch - GPIO5 */
 +#define stac_hp_bass_gpio_info        snd_ctl_boolean_mono_info
 +static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol,
 +                               struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 +      struct sigmatel_spec *spec = codec->spec;
 +      ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20);
 +      return 0;
 +}
 +
 +static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol,
 +                               struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 +      struct sigmatel_spec *spec = codec->spec;
 +      unsigned int gpio_data;
 +
 +      gpio_data = (spec->gpio_data & ~0x20) |
 +              (ucontrol->value.integer.value[0] ? 0x20 : 0);
 +      if (gpio_data == spec->gpio_data)
 +              return 0;
 +      spec->gpio_data = gpio_data;
 +      stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
 +      return 1;
 +}
 +
 +static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = {
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +      .info = stac_hp_bass_gpio_info,
 +      .get = stac_hp_bass_gpio_get,
 +      .put = stac_hp_bass_gpio_put,
 +};
 +
 +static int stac_add_hp_bass_switch(struct hda_codec *codec)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +
 +      if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl,
 +                            "Bass Speaker Playback Switch", 0))
 +              return -ENOMEM;
 +
 +      spec->gpio_mask |= 0x20;
 +      spec->gpio_dir |= 0x20;
 +      spec->gpio_data |= 0x20;
 +      return 0;
 +}
 +
  static int patch_stac92hd71bxx(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec;
@@@ -5603,6 -5575,8 +5630,8 @@@ again
        spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
        spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e);
  
+       snd_printdd("Found board config: %d\n", spec->board_config);
        switch (spec->board_config) {
        case STAC_HP_M4:
                /* enable internal microphone */
                return err;
        }
  
 +      /* enable bass on HP dv7 */
 +      if (spec->board_config == STAC_HP_DV5) {
 +              unsigned int cap;
 +              cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP);
 +              cap &= AC_GPIO_IO_COUNT;
 +              if (cap >= 6)
 +                      stac_add_hp_bass_switch(codec);
 +      }
 +
        codec->proc_widget_hook = stac92hd7x_proc_hook;
  
        return 0;
index bb08a2855fcedc9846a34ba1142d2ac28e7f0fd3,e66ef2b69b5d45a7424a161f6e90767628d98402..960a227eb6531795bbbdbdfa8430238939079a5c
@@@ -506,7 -506,7 +506,7 @@@ static int riptide_reset(struct cmdif *
  /*
   */
  
 -static struct pci_device_id snd_riptide_ids[] = {
 +static DEFINE_PCI_DEVICE_TABLE(snd_riptide_ids) = {
        { PCI_DEVICE(0x127a, 0x4310) },
        { PCI_DEVICE(0x127a, 0x4320) },
        { PCI_DEVICE(0x127a, 0x4330) },
  };
  
  #ifdef SUPPORT_JOYSTICK
 -static struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = {
 +static DEFINE_PCI_DEVICE_TABLE(snd_riptide_joystick_ids) = {
        { PCI_DEVICE(0x127a, 0x4312) },
        { PCI_DEVICE(0x127a, 0x4322) },
        { PCI_DEVICE(0x127a, 0x4332) },
@@@ -1058,7 -1058,7 +1058,7 @@@ setsamplerate(struct cmdif *cif, unsign
                                 rptr.retwords[2] != M &&
                                 rptr.retwords[3] != N &&
                                 i++ < MAX_WRITE_RETRY);
-                       if (i == MAX_WRITE_RETRY) {
+                       if (i > MAX_WRITE_RETRY) {
                                snd_printdd("sent samplerate %d: %d failed\n",
                                            *intdec, rate);
                                return -EIO;
diff --combined sound/usb/usbaudio.c
index 8a8f62515b80165d17280b7b83565d42d710cb58,9edef4684978f43285bd6e076532ab795cfb9ccb..c6b9c8cac59e3f08ed26e47b80c57eab89089084
@@@ -44,6 -44,7 +44,6 @@@
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/usb.h>
 -#include <linux/vmalloc.h>
  #include <linux/moduleparam.h>
  #include <linux/mutex.h>
  #include <sound/core.h>
@@@ -169,12 -170,11 +169,12 @@@ struct snd_usb_substream 
        unsigned int curpacksize;       /* current packet size in bytes (for capture) */
        unsigned int curframesize;      /* current packet size in frames (for capture) */
        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) */
  
        unsigned int running: 1;        /* running status */
  
 -      unsigned int hwptr_done;                        /* processed frame position in the buffer */
 +      unsigned int hwptr_done;        /* processed byte position in the buffer */
        unsigned int transfer_done;             /* processed frames since last period update */
        unsigned long active_mask;      /* bitmask of active urbs */
        unsigned long unlink_mask;      /* bitmask of unlinked urbs */
@@@ -343,7 -343,7 +343,7 @@@ static int retire_capture_urb(struct sn
        unsigned long flags;
        unsigned char *cp;
        int i;
 -      unsigned int stride, len, oldptr;
 +      unsigned int stride, frames, bytes, oldptr;
        int period_elapsed = 0;
  
        stride = runtime->frame_bits >> 3;
                        snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
                        // continue;
                }
 -              len = urb->iso_frame_desc[i].actual_length / stride;
 -              if (! len)
 -                      continue;
 +              bytes = urb->iso_frame_desc[i].actual_length;
 +              frames = bytes / stride;
 +              if (!subs->txfr_quirk)
 +                      bytes = frames * stride;
 +              if (bytes % (runtime->sample_bits >> 3) != 0) {
 +#ifdef CONFIG_SND_DEBUG_VERBOSE
 +                      int oldbytes = bytes;
 +#endif
 +                      bytes = frames * stride;
 +                      snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
 +                                                      oldbytes, bytes);
 +              }
                /* update the current pointer */
                spin_lock_irqsave(&subs->lock, flags);
                oldptr = subs->hwptr_done;
 -              subs->hwptr_done += len;
 -              if (subs->hwptr_done >= runtime->buffer_size)
 -                      subs->hwptr_done -= runtime->buffer_size;
 -              subs->transfer_done += len;
 +              subs->hwptr_done += bytes;
 +              if (subs->hwptr_done >= runtime->buffer_size * stride)
 +                      subs->hwptr_done -= runtime->buffer_size * stride;
 +              frames = (bytes + (oldptr % stride)) / stride;
 +              subs->transfer_done += frames;
                if (subs->transfer_done >= runtime->period_size) {
                        subs->transfer_done -= runtime->period_size;
                        period_elapsed = 1;
                }
                spin_unlock_irqrestore(&subs->lock, flags);
                /* copy a data chunk */
 -              if (oldptr + len > runtime->buffer_size) {
 -                      unsigned int cnt = runtime->buffer_size - oldptr;
 -                      unsigned int blen = cnt * stride;
 -                      memcpy(runtime->dma_area + oldptr * stride, cp, blen);
 -                      memcpy(runtime->dma_area, cp + blen, len * stride - blen);
 +              if (oldptr + bytes > runtime->buffer_size * stride) {
 +                      unsigned int bytes1 =
 +                                      runtime->buffer_size * stride - oldptr;
 +                      memcpy(runtime->dma_area + oldptr, cp, bytes1);
 +                      memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
                } else {
 -                      memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
 +                      memcpy(runtime->dma_area + oldptr, cp, bytes);
                }
        }
        if (period_elapsed)
@@@ -573,24 -563,24 +573,24 @@@ static int prepare_playback_urb(struct 
                                struct snd_pcm_runtime *runtime,
                                struct urb *urb)
  {
 -      int i, stride, offs;
 -      unsigned int counts;
 +      int i, stride;
 +      unsigned int counts, frames, bytes;
        unsigned long flags;
        int period_elapsed = 0;
        struct snd_urb_ctx *ctx = urb->context;
  
        stride = runtime->frame_bits >> 3;
  
 -      offs = 0;
 +      frames = 0;
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
        urb->number_of_packets = 0;
        spin_lock_irqsave(&subs->lock, flags);
        for (i = 0; i < ctx->packets; i++) {
                counts = snd_usb_audio_next_packet_size(subs);
                /* set up descriptor */
 -              urb->iso_frame_desc[i].offset = offs * stride;
 +              urb->iso_frame_desc[i].offset = frames * stride;
                urb->iso_frame_desc[i].length = counts * stride;
 -              offs += counts;
 +              frames += counts;
                urb->number_of_packets++;
                subs->transfer_done += counts;
                if (subs->transfer_done >= runtime->period_size) {
                                if (subs->transfer_done > 0) {
                                        /* FIXME: fill-max mode is not
                                         * supported yet */
 -                                      offs -= subs->transfer_done;
 +                                      frames -= subs->transfer_done;
                                        counts -= subs->transfer_done;
                                        urb->iso_frame_desc[i].length =
                                                counts * stride;
                                if (i < ctx->packets) {
                                        /* add a transfer delimiter */
                                        urb->iso_frame_desc[i].offset =
 -                                              offs * stride;
 +                                              frames * stride;
                                        urb->iso_frame_desc[i].length = 0;
                                        urb->number_of_packets++;
                                }
                if (period_elapsed) /* finish at the period boundary */
                        break;
        }
 -      if (subs->hwptr_done + offs > runtime->buffer_size) {
 +      bytes = frames * stride;
 +      if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
                /* err, the transferred area goes over buffer boundary. */
 -              unsigned int len = runtime->buffer_size - subs->hwptr_done;
 +              unsigned int bytes1 =
 +                      runtime->buffer_size * stride - subs->hwptr_done;
                memcpy(urb->transfer_buffer,
 -                     runtime->dma_area + subs->hwptr_done * stride,
 -                     len * stride);
 -              memcpy(urb->transfer_buffer + len * stride,
 -                     runtime->dma_area,
 -                     (offs - len) * stride);
 +                     runtime->dma_area + subs->hwptr_done, bytes1);
 +              memcpy(urb->transfer_buffer + bytes1,
 +                     runtime->dma_area, bytes - bytes1);
        } else {
                memcpy(urb->transfer_buffer,
 -                     runtime->dma_area + subs->hwptr_done * stride,
 -                     offs * stride);
 +                     runtime->dma_area + subs->hwptr_done, bytes);
        }
 -      subs->hwptr_done += offs;
 -      if (subs->hwptr_done >= runtime->buffer_size)
 -              subs->hwptr_done -= runtime->buffer_size;
 -      runtime->delay += offs;
 +      subs->hwptr_done += bytes;
 +      if (subs->hwptr_done >= runtime->buffer_size * stride)
 +              subs->hwptr_done -= runtime->buffer_size * stride;
 +      runtime->delay += frames;
        spin_unlock_irqrestore(&subs->lock, flags);
 -      urb->transfer_buffer_length = offs * stride;
 +      urb->transfer_buffer_length = bytes;
        if (period_elapsed)
                snd_pcm_period_elapsed(subs->pcm_substream);
        return 0;
@@@ -744,6 -735,41 +744,6 @@@ static void snd_complete_sync_urb(struc
  }
  
  
 -/* get the physical page pointer at the given offset */
 -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
 -                                           unsigned long offset)
 -{
 -      void *pageptr = subs->runtime->dma_area + offset;
 -      return vmalloc_to_page(pageptr);
 -}
 -
 -/* allocate virtual buffer; may be called more than once */
 -static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
 -{
 -      struct snd_pcm_runtime *runtime = subs->runtime;
 -      if (runtime->dma_area) {
 -              if (runtime->dma_bytes >= size)
 -                      return 0; /* already large enough */
 -              vfree(runtime->dma_area);
 -      }
 -      runtime->dma_area = vmalloc_user(size);
 -      if (!runtime->dma_area)
 -              return -ENOMEM;
 -      runtime->dma_bytes = size;
 -      return 0;
 -}
 -
 -/* free virtual buffer; may be called more than once */
 -static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
 -{
 -      struct snd_pcm_runtime *runtime = subs->runtime;
 -
 -      vfree(runtime->dma_area);
 -      runtime->dma_area = NULL;
 -      return 0;
 -}
 -
 -
  /*
   * unlink active urbs.
   */
@@@ -911,18 -937,18 +911,18 @@@ static int wait_clear_urbs(struct snd_u
  
  
  /*
 - * return the current pcm pointer.  just return the hwptr_done value.
 + * return the current pcm pointer.  just based on the hwptr_done value.
   */
  static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
  {
        struct snd_usb_substream *subs;
 -      snd_pcm_uframes_t hwptr_done;
 +      unsigned int hwptr_done;
        
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
        spin_unlock(&subs->lock);
 -      return hwptr_done;
 +      return hwptr_done / (substream->runtime->frame_bits >> 3);
  }
  
  
@@@ -1280,47 -1306,6 +1280,47 @@@ static int init_usb_sample_rate(struct 
        return 0;
  }
  
 +/*
 + * For E-Mu 0404USB/0202USB/TrackerPre sample rate should be set for device,
 + * not for interface.
 + */
 +static void set_format_emu_quirk(struct snd_usb_substream *subs,
 +                               struct audioformat *fmt)
 +{
 +      unsigned char emu_samplerate_id = 0;
 +
 +      /* When capture is active
 +       * sample rate shouldn't be changed
 +       * by playback substream
 +       */
 +      if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
 +              if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1)
 +                      return;
 +      }
 +
 +      switch (fmt->rate_min) {
 +      case 48000:
 +              emu_samplerate_id = EMU_QUIRK_SR_48000HZ;
 +              break;
 +      case 88200:
 +              emu_samplerate_id = EMU_QUIRK_SR_88200HZ;
 +              break;
 +      case 96000:
 +              emu_samplerate_id = EMU_QUIRK_SR_96000HZ;
 +              break;
 +      case 176400:
 +              emu_samplerate_id = EMU_QUIRK_SR_176400HZ;
 +              break;
 +      case 192000:
 +              emu_samplerate_id = EMU_QUIRK_SR_192000HZ;
 +              break;
 +      default:
 +              emu_samplerate_id = EMU_QUIRK_SR_44100HZ;
 +              break;
 +      }
 +      snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
 +}
 +
  /*
   * find a matching format and set up the interface
   */
@@@ -1434,14 -1419,6 +1434,14 @@@ static int set_format(struct snd_usb_su
  
        subs->cur_audiofmt = fmt;
  
 +      switch (subs->stream->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 */
 +              set_format_emu_quirk(subs, fmt);
 +              break;
 +      }
 +
  #if 0
        printk(KERN_DEBUG
               "setting done: format = %d, rate = %d..%d, channels = %d\n",
@@@ -1472,8 -1449,8 +1472,8 @@@ static int snd_usb_hw_params(struct snd
        unsigned int channels, rate, format;
        int ret, changed;
  
 -      ret = snd_pcm_alloc_vmalloc_buffer(substream,
 -                                         params_buffer_bytes(hw_params));
 +      ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
 +                                             params_buffer_bytes(hw_params));
        if (ret < 0)
                return ret;
  
@@@ -1530,7 -1507,7 +1530,7 @@@ static int snd_usb_hw_free(struct snd_p
        subs->period_bytes = 0;
        if (!subs->stream->chip->shutdown)
                release_substream_urbs(subs, 0);
 -      return snd_pcm_free_vmalloc_buffer(substream);
 +      return snd_pcm_lib_free_vmalloc_buffer(substream);
  }
  
  /*
@@@ -1959,7 -1936,7 +1959,7 @@@ static int snd_usb_pcm_close(struct snd
        struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
        struct snd_usb_substream *subs = &as->substream[direction];
  
-       if (subs->interface >= 0) {
+       if (!as->chip->shutdown && subs->interface >= 0) {
                usb_set_interface(subs->dev, subs->interface, 0);
                subs->interface = -1;
        }
@@@ -1996,8 -1973,7 +1996,8 @@@ static struct snd_pcm_ops snd_usb_playb
        .prepare =      snd_usb_pcm_prepare,
        .trigger =      snd_usb_pcm_playback_trigger,
        .pointer =      snd_usb_pcm_pointer,
 -      .page =         snd_pcm_get_vmalloc_page,
 +      .page =         snd_pcm_lib_get_vmalloc_page,
 +      .mmap =         snd_pcm_lib_mmap_vmalloc,
  };
  
  static struct snd_pcm_ops snd_usb_capture_ops = {
        .prepare =      snd_usb_pcm_prepare,
        .trigger =      snd_usb_pcm_capture_trigger,
        .pointer =      snd_usb_pcm_pointer,
 -      .page =         snd_pcm_get_vmalloc_page,
 +      .page =         snd_pcm_lib_get_vmalloc_page,
 +      .mmap =         snd_pcm_lib_mmap_vmalloc,
  };
  
  
@@@ -2252,7 -2227,6 +2252,7 @@@ static void init_substream(struct snd_u
        subs->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 {
@@@ -3168,6 -3142,59 +3168,6 @@@ static int create_ua1000_quirk(struct s
        return 0;
  }
  
 -/*
 - * Create a stream for an Edirol UA-101 interface.
 - * Copy, paste and modify from Edirol UA-1000
 - */
 -static int create_ua101_quirk(struct snd_usb_audio *chip,
 -                             struct usb_interface *iface,
 -                             const struct snd_usb_audio_quirk *quirk)
 -{
 -      static const struct audioformat ua101_format = {
 -              .format = SNDRV_PCM_FORMAT_S32_LE,
 -              .fmt_type = USB_FORMAT_TYPE_I,
 -              .altsetting = 1,
 -              .altset_idx = 1,
 -              .attributes = 0,
 -              .rates = SNDRV_PCM_RATE_CONTINUOUS,
 -      };
 -      struct usb_host_interface *alts;
 -      struct usb_interface_descriptor *altsd;
 -      struct audioformat *fp;
 -      int stream, err;
 -
 -      if (iface->num_altsetting != 2)
 -              return -ENXIO;
 -      alts = &iface->altsetting[1];
 -      altsd = get_iface_desc(alts);
 -      if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE ||
 -          altsd->bNumEndpoints != 1)
 -              return -ENXIO;
 -
 -      fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL);
 -      if (!fp)
 -              return -ENOMEM;
 -
 -      fp->channels = alts->extra[11];
 -      fp->iface = altsd->bInterfaceNumber;
 -      fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
 -      fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
 -      fp->datainterval = parse_datainterval(chip, alts);
 -      fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
 -      fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
 -
 -      stream = (fp->endpoint & USB_DIR_IN)
 -              ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
 -      err = add_audio_endpoint(chip, stream, fp);
 -      if (err < 0) {
 -              kfree(fp);
 -              return err;
 -      }
 -      /* FIXME: playback must be synchronized to capture */
 -      usb_set_interface(chip->dev, fp->iface, 0);
 -      return 0;
 -}
 -
  static int snd_usb_create_quirk(struct snd_usb_audio *chip,
                                struct usb_interface *iface,
                                const struct snd_usb_audio_quirk *quirk);
@@@ -3205,18 -3232,6 +3205,18 @@@ static int ignore_interface_quirk(struc
        return 0;
  }
  
 +/*
 + * Allow alignment on audio sub-slot (channel samples) rather than
 + * on audio slots (audio frames)
 + */
 +static int create_align_transfer_quirk(struct snd_usb_audio *chip,
 +                                struct usb_interface *iface,
 +                                const struct snd_usb_audio_quirk *quirk)
 +{
 +      chip->txfr_quirk = 1;
 +      return 1;       /* Continue with creating streams and mixer */
 +}
 +
  
  /*
   * boot quirks
@@@ -3311,32 -3326,6 +3311,32 @@@ static int snd_usb_cm6206_boot_quirk(st
        return err;
  }
  
 +/*
 + * This call will put the synth in "USB send" mode, i.e it will send MIDI
 + * messages through USB (this is disabled at startup). The synth will
 + * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB
 + * sign on its LCD. Values here are chosen based on sniffing USB traffic
 + * under Windows.
 + */
 +static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
 +{
 +      int err, actual_length;
 +
 +      /* "midi send" enable */
 +      static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
 +
 +      void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
 +      if (!buf)
 +              return -ENOMEM;
 +      err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf,
 +                      ARRAY_SIZE(seq), &actual_length, 1000);
 +      kfree(buf);
 +      if (err < 0)
 +              return err;
 +
 +      return 0;
 +}
 +
  /*
   * Setup quirks
   */
@@@ -3417,8 -3406,8 +3417,8 @@@ static int snd_usb_create_quirk(struct 
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
 -              [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk,
 -              [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk
 +              [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
 +              [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
        };
  
        if (quirk->type < QUIRK_TYPE_COUNT) {
@@@ -3635,12 -3624,6 +3635,12 @@@ static void *snd_usb_audio_probe(struc
                        goto __err_val;
        }
  
 +      /* Access Music VirusTI Desktop */
 +      if (id == USB_ID(0x133e, 0x0815)) {
 +              if (snd_usb_accessmusic_boot_quirk(dev) < 0)
 +                      goto __err_val;
 +      }
 +
        /*
         * found a config.  now register to ALSA
         */
                }
        }
  
 +      chip->txfr_quirk = 0;
        err = 1; /* continue */
        if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
                /* need some special handlings */