Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2011 17:10:51 +0000 (10:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2011 17:10:51 +0000 (10:10 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (26 commits)
  ASoC: Fix power down for widgetless per-card DAPM context case
  ASoC: wm1250-ev1: Define "WM1250 Output" with SND_SOC_DAPM_OUTPUT
  ASoC: Remove duplicate linux/delay.h inclusion.
  ASoC: sam9g20_wm8731: use the proper SYSCKL value
  ASoC: wm8731: fix wm8731_check_osc() connected condition
  ALSA: hda - Reorganize controller quriks with bit flags
  ALSA: hda - Use snd_printd() in snd_hda_parse_pin_def_config()
  ALSA: core: remove unused variables.
  ALSA: HDA: Increase MAX_HDMI_PINS
  ALSA: PCM - Don't check DMA time-out too shortly
  MAINTAINERS: add FireWire audio maintainer
  ALSA: usb-audio: more control quirks for M-Audio FastTrack devices
  ALSA: usb-audio: add new quirk type QUIRK_AUDIO_STANDARD_MIXER
  ALSA: usb-audio: export snd_usb_feature_unit_ctl
  ALSA: usb-audio: rework add_control_to_empty()
  ALSA: usb-audio: move assignment of chip->ctrl_intf
  ALSA: hda - Use model=auto for Lenovo G555
  ALSA: HDA: Unify HDMI hotplug handling.
  ALSA: hda - Force AD1988_6STACK_DIG for Asus M3N-HT Deluxe
  ASoC: core - remove superfluous new line.
  ...

27 files changed:
MAINTAINERS
sound/core/control.c
sound/core/init.c
sound/core/oss/linear.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/core/seq/seq_queue.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8915.c
sound/soc/pxa/raumfeld.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/usb/card.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_quirks.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usbaudio.h

index c4fc1da..572b5b2 100644 (file)
@@ -2584,6 +2584,13 @@ S:       Maintained
 F:     drivers/hwmon/f75375s.c
 F:     include/linux/f75375s.h
 
+FIREWIRE AUDIO DRIVERS
+M:     Clemens Ladisch <clemens@ladisch.de>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+T:     git git://git.alsa-project.org/alsa-kernel.git
+S:     Maintained
+F:     sound/firewire/
+
 FIREWIRE SUBSYSTEM
 M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
index 5d98194..f8c5be4 100644 (file)
@@ -704,13 +704,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
        struct snd_ctl_elem_list list;
        struct snd_kcontrol *kctl;
        struct snd_ctl_elem_id *dst, *id;
-       unsigned int offset, space, first, jidx;
+       unsigned int offset, space, jidx;
        
        if (copy_from_user(&list, _list, sizeof(list)))
                return -EFAULT;
        offset = list.offset;
        space = list.space;
-       first = 0;
        /* try limit maximum space */
        if (space > 16384)
                return -ENOMEM;
index 30ecad4..2c041bb 100644 (file)
@@ -342,7 +342,6 @@ static const struct file_operations snd_shutdown_f_ops =
 int snd_card_disconnect(struct snd_card *card)
 {
        struct snd_monitor_file *mfile;
-       struct file *file;
        int err;
 
        if (!card)
@@ -366,8 +365,6 @@ int snd_card_disconnect(struct snd_card *card)
        
        spin_lock(&card->files_lock);
        list_for_each_entry(mfile, &card->files_list, list) {
-               file = mfile->file;
-
                /* it's critical part, use endless loop */
                /* we have no room to fail */
                mfile->disconnected_f_op = mfile->file->f_op;
index 13b3f6f..2045697 100644 (file)
@@ -90,11 +90,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
                               struct snd_pcm_plugin_channel *dst_channels,
                               snd_pcm_uframes_t frames)
 {
-       struct linear_priv *data;
-
        if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
                return -ENXIO;
-       data = (struct linear_priv *)plugin->extra_data;
        if (frames == 0)
                return 0;
 #ifdef CONFIG_SND_DEBUG
index abfeff1..f134130 100644 (file)
@@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
        wait_queue_t wait;
        int err = 0;
        snd_pcm_uframes_t avail = 0;
-       long tout;
-
+       long wait_time, tout;
+
+       if (runtime->no_period_wakeup)
+               wait_time = MAX_SCHEDULE_TIMEOUT;
+       else {
+               wait_time = 10;
+               if (runtime->rate) {
+                       long t = runtime->period_size * 2 / runtime->rate;
+                       wait_time = max(t, wait_time);
+               }
+               wait_time = msecs_to_jiffies(wait_time * 1000);
+       }
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&runtime->tsleep, &wait);
        for (;;) {
@@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                        err = -ERESTARTSYS;
                        break;
                }
-               set_current_state(TASK_INTERRUPTIBLE);
                snd_pcm_stream_unlock_irq(substream);
-               tout = schedule_timeout(msecs_to_jiffies(10000));
+               tout = schedule_timeout_interruptible(wait_time);
                snd_pcm_stream_lock_irq(substream);
                switch (runtime->status->state) {
                case SNDRV_PCM_STATE_SUSPENDED:
index 1a07750..1c6be91 100644 (file)
@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                        break; /* all drained */
                init_waitqueue_entry(&wait, current);
                add_wait_queue(&to_check->sleep, &wait);
-               set_current_state(TASK_INTERRUPTIBLE);
                snd_pcm_stream_unlock_irq(substream);
                up_read(&snd_pcm_link_rwsem);
                snd_power_unlock(card);
-               tout = schedule_timeout(10 * HZ);
+               if (runtime->no_period_wakeup)
+                       tout = MAX_SCHEDULE_TIMEOUT;
+               else {
+                       tout = 10;
+                       if (runtime->rate) {
+                               long t = runtime->period_size * 2 / runtime->rate;
+                               tout = max(t, tout);
+                       }
+                       tout = msecs_to_jiffies(tout * 1000);
+               }
+               tout = schedule_timeout_interruptible(tout);
                snd_power_lock(card);
                down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
@@ -1518,13 +1527,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
 static int snd_pcm_drop(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
-       struct snd_card *card;
        int result = 0;
        
        if (PCM_RUNTIME_CHECK(substream))
                return -ENXIO;
        runtime = substream->runtime;
-       card = substream->pcm->card;
 
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
            runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
@@ -2056,7 +2063,6 @@ static int snd_pcm_open_file(struct file *file,
 {
        struct snd_pcm_file *pcm_file;
        struct snd_pcm_substream *substream;
-       struct snd_pcm_str *str;
        int err;
 
        if (rpcm_file)
@@ -2073,7 +2079,6 @@ static int snd_pcm_open_file(struct file *file,
        }
        pcm_file->substream = substream;
        if (substream->ref_count == 1) {
-               str = substream->pstr;
                substream->file = pcm_file;
                substream->pcm_release = pcm_release_private;
        }
@@ -3015,11 +3020,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status =
 static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
                               struct vm_area_struct *area)
 {
-       struct snd_pcm_runtime *runtime;
        long size;
        if (!(area->vm_flags & VM_READ))
                return -EINVAL;
-       runtime = substream->runtime;
        size = area->vm_end - area->vm_start;
        if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
                return -EINVAL;
@@ -3054,11 +3057,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control =
 static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
                                struct vm_area_struct *area)
 {
-       struct snd_pcm_runtime *runtime;
        long size;
        if (!(area->vm_flags & VM_READ))
                return -EINVAL;
-       runtime = substream->runtime;
        size = area->vm_end - area->vm_start;
        if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
                return -EINVAL;
index e7a8e9e..f907736 100644 (file)
@@ -467,13 +467,11 @@ int snd_seq_queue_timer_open(int queueid)
 int snd_seq_queue_timer_close(int queueid)
 {
        struct snd_seq_queue *queue;
-       struct snd_seq_timer *tmr;
        int result = 0;
 
        queue = queueptr(queueid);
        if (queue == NULL)
                return -EINVAL;
-       tmr = queue->timer;
        snd_seq_timer_close(queue);
        queuefree(queue);
        return result;
index 8edd998..45b4a8d 100644 (file)
@@ -4719,7 +4719,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                           cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
        snd_printd("   inputs:");
        for (i = 0; i < cfg->num_inputs; i++) {
-               snd_printdd(" %s=0x%x",
+               snd_printd(" %s=0x%x",
                            hda_get_autocfg_input_label(codec, cfg, i),
                            cfg->inputs[i].pin);
        }
index 74b0560..b05f7be 100644 (file)
@@ -312,23 +312,6 @@ out_fail:
        return -EINVAL;
 }
 
-static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
-{
-       int eldv;
-       int present;
-
-       present = snd_hda_pin_sense(codec, nid);
-       eldv    = (present & AC_PINSENSE_ELDV);
-       present = (present & AC_PINSENSE_PRESENCE);
-
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-       printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n",
-                       !!present, !!eldv);
-#endif
-
-       return eldv && present;
-}
-
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
 {
        return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
@@ -343,7 +326,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
        int size;
        unsigned char *buf;
 
-       if (!hdmi_eld_valid(codec, nid))
+       if (!eld->eld_valid)
                return -ENOENT;
 
        size = snd_hdmi_get_eld_size(codec, nid);
@@ -477,6 +460,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
 
        snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present);
        snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid);
+       if (!e->eld_valid)
+               return;
        snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
        snd_iprintf(buffer, "connection_type\t\t%s\n",
                                eld_connection_type_names[e->conn_type]);
index 43a0367..3487056 100644 (file)
@@ -391,6 +391,7 @@ struct azx {
 
        /* chip type specific */
        int driver_type;
+       unsigned int driver_caps;
        int playback_streams;
        int playback_index_offset;
        int capture_streams;
@@ -464,6 +465,34 @@ enum {
        AZX_NUM_DRIVERS, /* keep this as last entry */
 };
 
+/* driver quirks (capabilities) */
+/* bits 0-7 are used for indicating driver type */
+#define AZX_DCAPS_NO_TCSEL     (1 << 8)        /* No Intel TCSEL bit */
+#define AZX_DCAPS_NO_MSI       (1 << 9)        /* No MSI support */
+#define AZX_DCAPS_ATI_SNOOP    (1 << 10)       /* ATI snoop enable */
+#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11)       /* Nvidia snoop enable */
+#define AZX_DCAPS_SCH_SNOOP    (1 << 12)       /* SCH/PCH snoop enable */
+#define AZX_DCAPS_RIRB_DELAY   (1 << 13)       /* Long delay in read loop */
+#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14)     /* Put a delay before read */
+#define AZX_DCAPS_CTX_WORKAROUND (1 << 15)     /* X-Fi workaround */
+#define AZX_DCAPS_POSFIX_LPIB  (1 << 16)       /* Use LPIB as default */
+#define AZX_DCAPS_POSFIX_VIA   (1 << 17)       /* Use VIACOMBO as default */
+#define AZX_DCAPS_NO_64BIT     (1 << 18)       /* No 64bit address */
+#define AZX_DCAPS_SYNC_WRITE   (1 << 19)       /* sync each cmd write */
+
+/* quirks for ATI SB / AMD Hudson */
+#define AZX_DCAPS_PRESET_ATI_SB \
+       (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \
+        AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB)
+
+/* quirks for ATI/AMD HDMI */
+#define AZX_DCAPS_PRESET_ATI_HDMI \
+       (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB)
+
+/* quirks for Nvidia */
+#define AZX_DCAPS_PRESET_NVIDIA \
+       (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI)
+
 static char *driver_short_names[] __devinitdata = {
        [AZX_DRIVER_ICH] = "HDA Intel",
        [AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -566,7 +595,7 @@ static void azx_init_cmd_io(struct azx *chip)
        /* reset the rirb hw write pointer */
        azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
        /* set N=1, get RIRB response interrupt for new entry */
-       if (chip->driver_type == AZX_DRIVER_CTX)
+       if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
                azx_writew(chip, RINTCNT, 0xc0);
        else
                azx_writew(chip, RINTCNT, 1);
@@ -1056,19 +1085,24 @@ static void azx_init_pci(struct azx *chip)
         * codecs.
         * The PCI register TCSEL is defined in the Intel manuals.
         */
-       if (chip->driver_type != AZX_DRIVER_ATI &&
-           chip->driver_type != AZX_DRIVER_ATIHDMI)
+       if (chip->driver_caps & AZX_DCAPS_NO_TCSEL) {
+               snd_printdd(SFX "Clearing TCSEL\n");
                update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+       }
 
-       switch (chip->driver_type) {
-       case AZX_DRIVER_ATI:
-               /* For ATI SB450 azalia HD audio, we need to enable snoop */
+       /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
+        * we need to enable snoop.
+        */
+       if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
+               snd_printdd(SFX "Enabling ATI snoop\n");
                update_pci_byte(chip->pci,
                                ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
                                0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
-               break;
-       case AZX_DRIVER_NVIDIA:
-               /* For NVIDIA HDA, enable snoop */
+       }
+
+       /* For NVIDIA HDA, enable snoop */
+       if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) {
+               snd_printdd(SFX "Enabling Nvidia snoop\n");
                update_pci_byte(chip->pci,
                                NVIDIA_HDA_TRANSREG_ADDR,
                                0x0f, NVIDIA_HDA_ENABLE_COHBITS);
@@ -1078,9 +1112,10 @@ static void azx_init_pci(struct azx *chip)
                update_pci_byte(chip->pci,
                                NVIDIA_HDA_OSTRM_COH,
                                0x01, NVIDIA_HDA_ENABLE_COHBIT);
-               break;
-       case AZX_DRIVER_SCH:
-       case AZX_DRIVER_PCH:
+       }
+
+       /* Enable SCH/PCH snoop if needed */
+       if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) {
                pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
                if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
                        pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
@@ -1091,14 +1126,6 @@ static void azx_init_pci(struct azx *chip)
                                (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
                                ? "Failed" : "OK");
                }
-               break;
-       default:
-               /* AMD Hudson needs the similar snoop, as it seems... */
-               if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
-                       update_pci_byte(chip->pci,
-                               ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
-                               0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
-               break;
         }
 }
 
@@ -1152,7 +1179,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
        status = azx_readb(chip, RIRBSTS);
        if (status & RIRB_INT_MASK) {
                if (status & RIRB_INT_RESPONSE) {
-                       if (chip->driver_type == AZX_DRIVER_CTX)
+                       if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY)
                                udelay(80);
                        azx_update_rirb(chip);
                }
@@ -1421,8 +1448,10 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
        if (err < 0)
                return err;
 
-       if (chip->driver_type == AZX_DRIVER_NVIDIA)
+       if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
+               snd_printd(SFX "Enable delay in RIRB handling\n");
                chip->bus->needs_damn_long_delay = 1;
+       }
 
        codecs = 0;
        max_slots = azx_max_codecs[chip->driver_type];
@@ -1457,9 +1486,8 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
         * sequence like the pin-detection.  It seems that forcing the synced
         * access works around the stall.  Grrr...
         */
-       if (chip->pci->vendor == PCI_VENDOR_ID_AMD ||
-           chip->pci->vendor == PCI_VENDOR_ID_ATI) {
-               snd_printk(KERN_INFO SFX "Enable sync_write for AMD chipset\n");
+       if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) {
+               snd_printd(SFX "Enable sync_write for stable communication\n");
                chip->bus->sync_write = 1;
                chip->bus->allow_bus_reset = 1;
        }
@@ -1720,7 +1748,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 
        stream_tag = azx_dev->stream_tag;
        /* CA-IBG chips need the playback stream starting from 1 */
-       if (chip->driver_type == AZX_DRIVER_CTX &&
+       if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
            stream_tag > chip->capture_streams)
                stream_tag -= chip->capture_streams;
        return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
@@ -2365,20 +2393,14 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
        }
 
        /* Check VIA/ATI HD Audio Controller exist */
-       switch (chip->driver_type) {
-       case AZX_DRIVER_VIA:
-               /* Use link position directly, avoid any transfer problem. */
+       if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
+               snd_printd(SFX "Using VIACOMBO position fix\n");
                return POS_FIX_VIACOMBO;
-       case AZX_DRIVER_ATI:
-               /* ATI chipsets don't work well with position-buffer */
+       }
+       if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
+               snd_printd(SFX "Using LPIB position fix\n");
                return POS_FIX_LPIB;
-       case AZX_DRIVER_GENERIC:
-               /* AMD chipsets also don't work with position-buffer */
-               if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
-                       return POS_FIX_LPIB;
-               break;
        }
-
        return POS_FIX_AUTO;
 }
 
@@ -2460,8 +2482,8 @@ static void __devinit check_msi(struct azx *chip)
        }
 
        /* NVidia chipsets seem to cause troubles with MSI */
-       if (chip->driver_type == AZX_DRIVER_NVIDIA) {
-               printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n");
+       if (chip->driver_caps & AZX_DCAPS_NO_MSI) {
+               printk(KERN_INFO "hda_intel: Disabling MSI\n");
                chip->msi = 0;
        }
 }
@@ -2471,7 +2493,7 @@ static void __devinit check_msi(struct azx *chip)
  * constructor
  */
 static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
-                               int dev, int driver_type,
+                               int dev, unsigned int driver_caps,
                                struct azx **rchip)
 {
        struct azx *chip;
@@ -2499,7 +2521,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       chip->driver_type = driver_type;
+       chip->driver_caps = driver_caps;
+       chip->driver_type = driver_caps & 0xff;
        check_msi(chip);
        chip->dev_index = dev;
        INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
@@ -2563,8 +2586,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
 
        /* disable SB600 64bit support for safety */
-       if ((chip->driver_type == AZX_DRIVER_ATI) ||
-           (chip->driver_type == AZX_DRIVER_ATIHDMI)) {
+       if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
                struct pci_dev *p_smbus;
                p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
                                         PCI_DEVICE_ID_ATI_SBX00_SMBUS,
@@ -2574,19 +2596,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                                gcap &= ~ICH6_GCAP_64OK;
                        pci_dev_put(p_smbus);
                }
-       } else {
-               /* FIXME: not sure whether this is really needed, but
-                * Hudson isn't stable enough for allowing everything...
-                * let's check later again.
-                */
-               if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
-                       gcap &= ~ICH6_GCAP_64OK;
        }
 
-       /* disable 64bit DMA address for Teradici */
-       /* it does not work with device 6549:1200 subsys e4a2:040b */
-       if (chip->driver_type == AZX_DRIVER_TERA)
+       /* disable 64bit DMA address on some devices */
+       if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
+               snd_printd(SFX "Disabling 64bit DMA\n");
                gcap &= ~ICH6_GCAP_64OK;
+       }
 
        /* allow 64bit DMA address if supported by H/W */
        if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
@@ -2788,38 +2804,62 @@ static void __devexit azx_remove(struct pci_dev *pci)
 /* PCI IDs */
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* CPT */
-       { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
+       { PCI_DEVICE(0x8086, 0x1c20),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
        /* PBG */
-       { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
+       { PCI_DEVICE(0x8086, 0x1d20),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
        /* Panther Point */
-       { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH },
+       { PCI_DEVICE(0x8086, 0x1e20),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
        /* SCH */
-       { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+       { PCI_DEVICE(0x8086, 0x811b),
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP },
        /* Generic Intel */
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
          .driver_data = AZX_DRIVER_ICH },
-       /* ATI SB 450/600 */
-       { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
-       { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
+       /* ATI SB 450/600/700/800/900 */
+       { PCI_DEVICE(0x1002, 0x437b),
+         .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
+       { PCI_DEVICE(0x1002, 0x4383),
+         .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
+       /* AMD Hudson */
+       { PCI_DEVICE(0x1022, 0x780d),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
        /* ATI HDMI */
-       { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0x970f), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
-       { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0x793b),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0x7919),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0x960f),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0x970f),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa00),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa08),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa10),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa18),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa20),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa28),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa30),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa38),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa40),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+       { PCI_DEVICE(0x1002, 0xaa48),
+         .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
        /* VIA VT8251/VT8237A */
-       { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
+       { PCI_DEVICE(0x1106, 0x3288),
+         .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
        /* SIS966 */
        { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
        /* ULI M5461 */
@@ -2828,9 +2868,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
-         .driver_data = AZX_DRIVER_NVIDIA },
+         .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA },
        /* Teradici */
-       { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+       { PCI_DEVICE(0x6549, 0x1200),
+         .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
        /* Creative X-Fi (CA0110-IBG) */
 #if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE)
        /* the following entry conflicts with snd-ctxfi driver,
@@ -2840,10 +2881,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
-         .driver_data = AZX_DRIVER_CTX },
+         .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+         AZX_DCAPS_RIRB_PRE_DELAY },
 #else
        /* this entry seems still valid -- i.e. without emu20kx chip */
-       { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX },
+       { PCI_DEVICE(0x1102, 0x0009),
+         .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+         AZX_DCAPS_RIRB_PRE_DELAY },
 #endif
        /* Vortex86MX */
        { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
@@ -2853,11 +2897,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
-         .driver_data = AZX_DRIVER_GENERIC },
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
-         .driver_data = AZX_DRIVER_GENERIC },
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
index f1b3875..696ac25 100644 (file)
@@ -3159,6 +3159,7 @@ static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
        SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
        SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
+       SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
        SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
        {}
 };
index 4f37477..3e6b9a8 100644 (file)
@@ -3098,7 +3098,9 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
+       SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
        {}
 };
@@ -3433,7 +3435,9 @@ static void cx_auto_parse_output(struct hda_codec *codec)
                        break;
                }
        }
-       if (spec->auto_mute && cfg->line_out_pins[0] &&
+       if (spec->auto_mute &&
+           cfg->line_out_pins[0] &&
+           cfg->line_out_type != AUTO_PIN_SPEAKER_OUT &&
            cfg->line_out_pins[0] != cfg->hp_pins[0] &&
            cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
                for (i = 0; i < cfg->line_outs; i++) {
@@ -3481,25 +3485,32 @@ static void cx_auto_update_speakers(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int on;
+       int on = 1;
 
-       if (!spec->auto_mute)
-               on = 0;
-       else
-               on = spec->hp_present | spec->line_present;
+       /* turn on HP EAPD when HP jacks are present */
+       if (spec->auto_mute)
+               on = spec->hp_present;
        cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
-       do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, !on);
+       /* mute speakers in auto-mode if HP or LO jacks are plugged */
+       if (spec->auto_mute)
+               on = !(spec->hp_present ||
+                      (spec->detect_line && spec->line_present));
+       do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, on);
 
        /* toggle line-out mutes if needed, too */
        /* if LO is a copy of either HP or Speaker, don't need to handle it */
        if (cfg->line_out_pins[0] == cfg->hp_pins[0] ||
            cfg->line_out_pins[0] == cfg->speaker_pins[0])
                return;
-       if (!spec->automute_lines || !spec->auto_mute)
-               on = 0;
-       else
-               on = spec->hp_present;
-       do_automute(codec, cfg->line_outs, cfg->line_out_pins, !on);
+       if (spec->auto_mute) {
+               /* mute LO in auto-mode when HP jack is present */
+               if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ||
+                   spec->automute_lines)
+                       on = !spec->hp_present;
+               else
+                       on = 1;
+       }
+       do_automute(codec, cfg->line_outs, cfg->line_out_pins, on);
 }
 
 static void cx_auto_hp_automute(struct hda_codec *codec)
@@ -3696,13 +3707,14 @@ static int cx_auto_mux_enum_update(struct hda_codec *codec,
 {
        struct conexant_spec *spec = codec->spec;
        hda_nid_t adc;
+       int changed = 1;
 
        if (!imux->num_items)
                return 0;
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
        if (spec->cur_mux[0] == idx)
-               return 0;
+               changed = 0;
        adc = spec->imux_info[idx].adc;
        select_input_connection(codec, spec->imux_info[idx].adc,
                                spec->imux_info[idx].pin);
@@ -3715,7 +3727,7 @@ static int cx_auto_mux_enum_update(struct hda_codec *codec,
                                           spec->cur_adc_format);
        }
        spec->cur_mux[0] = idx;
-       return 1;
+       return changed;
 }
 
 static int cx_auto_mux_enum_put(struct snd_kcontrol *kcontrol,
@@ -3789,7 +3801,7 @@ static void cx_auto_check_auto_mic(struct hda_codec *codec)
        int pset[INPUT_PIN_ATTR_NORMAL + 1];
        int i;
 
-       for (i = 0; i < INPUT_PIN_ATTR_NORMAL; i++)
+       for (i = 0; i < ARRAY_SIZE(pset); i++)
                pset[i] = -1;
        for (i = 0; i < spec->private_imux.num_items; i++) {
                hda_nid_t pin = spec->imux_info[i].pin;
index 3229018..bd0ae69 100644 (file)
@@ -48,8 +48,8 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
  *
  * The HDA correspondence of pipes/ports are converter/pin nodes.
  */
-#define MAX_HDMI_CVTS  3
-#define MAX_HDMI_PINS  3
+#define MAX_HDMI_CVTS  4
+#define MAX_HDMI_PINS  4
 
 struct hdmi_spec {
        int num_cvts;
@@ -78,10 +78,6 @@ struct hdmi_spec {
         */
        struct hda_multi_out multiout;
        const struct hda_pcm_stream *pcm_playback;
-
-       /* misc flags */
-       /* PD bit indicates only the update, not the current state */
-       unsigned int old_pin_detect:1;
 };
 
 
@@ -300,13 +296,6 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
        return -EINVAL;
 }
 
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-                             struct hdmi_eld *eld)
-{
-       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-               snd_hdmi_show_eld(eld);
-}
-
 #ifdef BE_PARANOID
 static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
                                int *packet_index, int *byte_index)
@@ -694,35 +683,20 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 {
        struct hdmi_spec *spec = codec->spec;
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pind = !!(res & AC_UNSOL_RES_PD);
+       int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT;
+       int pd = !!(res & AC_UNSOL_RES_PD);
        int eldv = !!(res & AC_UNSOL_RES_ELDV);
        int index;
 
        printk(KERN_INFO
                "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               tag, pind, eldv);
+               pin_nid, pd, eldv);
 
-       index = hda_node_index(spec->pin, tag);
+       index = hda_node_index(spec->pin, pin_nid);
        if (index < 0)
                return;
 
-       if (spec->old_pin_detect) {
-               if (pind)
-                       hdmi_present_sense(codec, tag, &spec->sink_eld[index]);
-               pind = spec->sink_eld[index].monitor_present;
-       }
-
-       spec->sink_eld[index].monitor_present = pind;
-       spec->sink_eld[index].eld_valid = eldv;
-
-       if (pind && eldv) {
-               hdmi_get_show_eld(codec, spec->pin[index],
-                                 &spec->sink_eld[index]);
-               /* TODO: do real things about ELD */
-       }
-
-       snd_hda_input_jack_report(codec, tag);
+       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[index]);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -903,13 +877,33 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
 static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
                               struct hdmi_eld *eld)
 {
+       /*
+        * Always execute a GetPinSense verb here, even when called from
+        * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
+        * response's PD bit is not the real PD value, but indicates that
+        * the real PD value changed. An older version of the HD-audio
+        * specification worked this way. Hence, we just ignore the data in
+        * the unsolicited response to avoid custom WARs.
+        */
        int present = snd_hda_pin_sense(codec, pin_nid);
 
+       memset(eld, 0, sizeof(*eld));
+
        eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
-       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
+       if (eld->monitor_present)
+               eld->eld_valid  = !!(present & AC_PINSENSE_ELDV);
+       else
+               eld->eld_valid  = 0;
 
-       if (present & AC_PINSENSE_ELDV)
-               hdmi_get_show_eld(codec, pin_nid, eld);
+       printk(KERN_INFO
+               "HDMI status: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+               pin_nid, eld->monitor_present, eld->eld_valid);
+
+       if (eld->eld_valid)
+               if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+                       snd_hdmi_show_eld(eld);
+
+       snd_hda_input_jack_report(codec, pin_nid);
 }
 
 static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
@@ -927,7 +921,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
                                     SND_JACK_VIDEOOUT, NULL);
        if (err < 0)
                return err;
-       snd_hda_input_jack_report(codec, pin_nid);
 
        hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
 
@@ -1034,6 +1027,7 @@ static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = {
        "HDMI 0",
        "HDMI 1",
        "HDMI 2",
+       "HDMI 3",
 };
 
 /*
@@ -1490,18 +1484,6 @@ static const struct hda_codec_ops nvhdmi_patch_ops_2ch = {
        .free = generic_hdmi_free,
 };
 
-static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec;
-       int err = patch_generic_hdmi(codec);
-
-       if (err < 0)
-               return err;
-       spec = codec->spec;
-       spec->old_pin_detect = 1;
-       return 0;
-}
-
 static int patch_nvhdmi_2ch(struct hda_codec *codec)
 {
        struct hdmi_spec *spec;
@@ -1515,7 +1497,6 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
        spec->multiout.num_dacs = 0;  /* no analog */
        spec->multiout.max_channels = 2;
        spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
-       spec->old_pin_detect = 1;
        spec->num_cvts = 1;
        spec->cvt[0] = nvhdmi_master_con_nid_7x;
        spec->pcm_playback = &nvhdmi_pcm_playback_2ch;
@@ -1658,28 +1639,28 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x10de0005, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
 { .id = 0x10de0006, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
 { .id = 0x10de0007, .name = "MCP79/7A HDMI",   .patch = patch_nvhdmi_8ch_7x },
-{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000c, .name = "MCP89 HDMI",      .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de000c, .name = "MCP89 HDMI",      .patch = patch_generic_hdmi },
+{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP",  .patch = patch_generic_hdmi },
 /* 17 is known to be absent */
-{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP",  .patch = patch_generic_hdmi },
 { .id = 0x10de0067, .name = "MCP67 HDMI",      .patch = patch_nvhdmi_2ch },
 { .id = 0x10de8001, .name = "MCP73 HDMI",      .patch = patch_nvhdmi_2ch },
 { .id = 0x80860054, .name = "IbexPeak HDMI",   .patch = patch_generic_hdmi },
index 28afbbf..95572d2 100644 (file)
@@ -146,7 +146,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
                        "at91sam9g20ek_wm8731 "
                        ": at91sam9g20ek_wm8731_init() called\n");
 
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK,
                MCLK_RATE, SND_SOC_CLOCK_IN);
        if (ret < 0) {
                printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
index 14d0716..bcc2089 100644 (file)
@@ -22,7 +22,7 @@ SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
 SND_SOC_DAPM_DAC("DAC", "wm1250-ev1 Playback", SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_INPUT("WM1250 Input"),
-SND_SOC_DAPM_INPUT("WM1250 Output"),
+SND_SOC_DAPM_OUTPUT("WM1250 Output"),
 };
 
 static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = {
index 6dec7ce..2dc964b 100644 (file)
@@ -198,7 +198,7 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
 {
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
 
-       return wm8731->sysclk_type == WM8731_SYSCLK_MCLK;
+       return wm8731->sysclk_type == WM8731_SYSCLK_XTAL;
 }
 
 static const struct snd_soc_dapm_route wm8731_intercon[] = {
index ccc9bd8..a0b1a72 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
index 2afabaf..1a591f1 100644 (file)
@@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = {
        .hw_params = raumfeld_cs4270_hw_params,
 };
 
-static int raumfeld_line_suspend(struct snd_soc_card *card)
+static int raumfeld_analog_suspend(struct snd_soc_card *card)
 {
        raumfeld_enable_audio(false);
        return 0;
 }
 
-static int raumfeld_line_resume(struct snd_soc_card *card)
+static int raumfeld_analog_resume(struct snd_soc_card *card)
 {
        raumfeld_enable_audio(true);
        return 0;
@@ -225,32 +225,53 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
        .hw_params = raumfeld_ak4104_hw_params,
 };
 
-static struct snd_soc_dai_link raumfeld_dai[] = {
+#define DAI_LINK_CS4270                \
+{                                                      \
+       .name           = "CS4270",                     \
+       .stream_name    = "CS4270",                     \
+       .cpu_dai_name   = "pxa-ssp-dai.0",              \
+       .platform_name  = "pxa-pcm-audio",              \
+       .codec_dai_name = "cs4270-hifi",                \
+       .codec_name     = "cs4270-codec.0-0048",        \
+       .ops            = &raumfeld_cs4270_ops,         \
+}
+
+#define DAI_LINK_AK4104                \
+{                                                      \
+       .name           = "ak4104",                     \
+       .stream_name    = "Playback",                   \
+       .cpu_dai_name   = "pxa-ssp-dai.1",              \
+       .codec_dai_name = "ak4104-hifi",                \
+       .platform_name  = "pxa-pcm-audio",              \
+       .ops            = &raumfeld_ak4104_ops,         \
+       .codec_name     = "spi0.0",                     \
+}
+
+static struct snd_soc_dai_link snd_soc_raumfeld_connector_dai[] =
 {
-       .name           = "ak4104",
-       .stream_name    = "Playback",
-       .cpu_dai_name   = "pxa-ssp-dai.1",
-       .codec_dai_name = "ak4104-hifi",
-       .platform_name  = "pxa-pcm-audio",
-       .ops            = &raumfeld_ak4104_ops,
-       .codec_name     = "ak4104-codec.0",
-},
+       DAI_LINK_CS4270,
+       DAI_LINK_AK4104,
+};
+
+static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] =
 {
-       .name           = "CS4270",
-       .stream_name    = "CS4270",
-       .cpu_dai_name   = "pxa-ssp-dai.0",
-       .platform_name  = "pxa-pcm-audio",
-       .codec_dai_name = "cs4270-hifi",
-       .codec_name     = "cs4270-codec.0-0048",
-       .ops            = &raumfeld_cs4270_ops,
-},};
-
-static struct snd_soc_card snd_soc_raumfeld = {
-       .name           = "Raumfeld",
-       .dai_link       = raumfeld_dai,
-       .suspend_post   = raumfeld_line_suspend,
-       .resume_pre     = raumfeld_line_resume,
-       .num_links      = ARRAY_SIZE(raumfeld_dai),
+       DAI_LINK_CS4270,
+};
+
+static struct snd_soc_card snd_soc_raumfeld_connector = {
+       .name           = "Raumfeld Connector",
+       .dai_link       = snd_soc_raumfeld_connector_dai,
+       .num_links      = ARRAY_SIZE(snd_soc_raumfeld_connector_dai),
+       .suspend_post   = raumfeld_analog_suspend,
+       .resume_pre     = raumfeld_analog_resume,
+};
+
+static struct snd_soc_card snd_soc_raumfeld_speaker = {
+       .name           = "Raumfeld Speaker",
+       .dai_link       = snd_soc_raumfeld_speaker_dai,
+       .num_links      = ARRAY_SIZE(snd_soc_raumfeld_speaker_dai),
+       .suspend_post   = raumfeld_analog_suspend,
+       .resume_pre     = raumfeld_analog_resume,
 };
 
 static struct platform_device *raumfeld_audio_device;
@@ -271,22 +292,25 @@ static int __init raumfeld_audio_init(void)
 
        set_max9485_clk(MAX9485_MCLK_FREQ_122880);
 
-       /* Register LINE and SPDIF */
+       /* Register analog device */
        raumfeld_audio_device = platform_device_alloc("soc-audio", 0);
        if (!raumfeld_audio_device)
                return -ENOMEM;
 
-       platform_set_drvdata(raumfeld_audio_device,
-                            &snd_soc_raumfeld);
-       ret = platform_device_add(raumfeld_audio_device);
-
-       /* no S/PDIF on Speakers */
        if (machine_is_raumfeld_speaker())
+               platform_set_drvdata(raumfeld_audio_device,
+                                    &snd_soc_raumfeld_speaker);
+
+       if (machine_is_raumfeld_connector())
+               platform_set_drvdata(raumfeld_audio_device,
+                                    &snd_soc_raumfeld_connector);
+
+       ret = platform_device_add(raumfeld_audio_device);
+       if (ret < 0)
                return ret;
 
        raumfeld_enable_audio(true);
-
-       return ret;
+       return 0;
 }
 
 static void __exit raumfeld_audio_exit(void)
index bb7cd58..d75043e 100644 (file)
@@ -1306,10 +1306,6 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
        /* no, then find CPU DAI from registered DAIs*/
        list_for_each_entry(cpu_dai, &dai_list, list) {
                if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
-
-                       if (!try_module_get(cpu_dai->dev->driver->owner))
-                               return -ENODEV;
-
                        rtd->cpu_dai = cpu_dai;
                        goto find_codec;
                }
@@ -1622,11 +1618,15 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 
        /* probe the cpu_dai */
        if (!cpu_dai->probed) {
+               if (!try_module_get(cpu_dai->dev->driver->owner))
+                       return -ENODEV;
+
                if (cpu_dai->driver->probe) {
                        ret = cpu_dai->driver->probe(cpu_dai);
                        if (ret < 0) {
                                printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
                                                cpu_dai->name);
+                               module_put(cpu_dai->dev->driver->owner);
                                return ret;
                        }
                }
index 456617e..999bb08 100644 (file)
@@ -1110,7 +1110,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
        trace_snd_soc_dapm_start(card);
 
        list_for_each_entry(d, &card->dapm_list, list)
-               if (d->n_widgets)
+               if (d->n_widgets || d->codec == NULL)
                        d->dev_power = 0;
 
        /* Check which widgets we need to power and store them in
index a90662a..220c616 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/usb/audio.h>
 #include <linux/usb/audio-v2.h>
 
+#include <sound/control.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/pcm.h>
@@ -492,14 +493,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                }
        }
 
-       chip->txfr_quirk = 0;
-       err = 1; /* continue */
-       if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
-               /* need some special handlings */
-               if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
-                       goto __error;
-       }
-
        /*
         * For devices with more than one control interface, we assume the
         * first contains the audio controls. We might need a more specific
@@ -508,6 +501,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
        if (!chip->ctrl_intf)
                chip->ctrl_intf = alts;
 
+       chip->txfr_quirk = 0;
+       err = 1; /* continue */
+       if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
+               /* need some special handlings */
+               if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
+                       goto __error;
+       }
+
        if (err > 0) {
                /* create normal USB audio interfaces */
                if (snd_usb_create_streams(chip, ifnum) < 0 ||
index eab06ed..c22fa76 100644 (file)
@@ -86,16 +86,6 @@ struct mixer_build {
        const struct usbmix_selector_map *selector_map;
 };
 
-enum {
-       USB_MIXER_BOOLEAN,
-       USB_MIXER_INV_BOOLEAN,
-       USB_MIXER_S8,
-       USB_MIXER_U8,
-       USB_MIXER_S16,
-       USB_MIXER_U16,
-};
-
-
 /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/
 enum {
        USB_XU_CLOCK_RATE               = 0xe301,
@@ -535,20 +525,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
  * if failed, give up and free the control instance.
  */
 
-static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl)
+int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
+                             struct snd_kcontrol *kctl)
 {
        struct usb_mixer_elem_info *cval = kctl->private_data;
        int err;
 
-       while (snd_ctl_find_id(state->chip->card, &kctl->id))
+       while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
                kctl->id.index++;
-       if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
+       if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
                snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
                return err;
        }
        cval->elem_id = &kctl->id;
-       cval->next_id_elem = state->mixer->id_elems[cval->id];
-       state->mixer->id_elems[cval->id] = cval;
+       cval->next_id_elem = mixer->id_elems[cval->id];
+       mixer->id_elems[cval->id] = cval;
        return 0;
 }
 
@@ -984,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
        .put = NULL,
 };
 
+/* This symbol is exported in order to allow the mixer quirks to
+ * hook up to the standard feature unit control mechanism */
+struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
 
 /*
  * build a feature control
@@ -1176,7 +1170,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 
        snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
                    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
-       add_control_to_empty(state, kctl);
+       snd_usb_mixer_add_control(state->mixer, kctl);
 }
 
 
@@ -1340,7 +1334,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
 
        snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
                    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-       add_control_to_empty(state, kctl);
+       snd_usb_mixer_add_control(state->mixer, kctl);
 }
 
 
@@ -1641,7 +1635,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
 
                snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
                            cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-               if ((err = add_control_to_empty(state, kctl)) < 0)
+               if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
                        return err;
        }
        return 0;
@@ -1858,7 +1852,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
 
        snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
                    cval->id, kctl->id.name, desc->bNrInPins);
-       if ((err = add_control_to_empty(state, kctl)) < 0)
+       if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
                return err;
 
        return 0;
index b4a2c81..ae1a14d 100644 (file)
@@ -24,7 +24,16 @@ struct usb_mixer_interface {
        u8 xonar_u1_status;
 };
 
-#define MAX_CHANNELS   10      /* max logical channels */
+#define MAX_CHANNELS   16      /* max logical channels */
+
+enum {
+       USB_MIXER_BOOLEAN,
+       USB_MIXER_INV_BOOLEAN,
+       USB_MIXER_S8,
+       USB_MIXER_U8,
+       USB_MIXER_S16,
+       USB_MIXER_U16,
+};
 
 struct usb_mixer_elem_info {
        struct usb_mixer_interface *mixer;
@@ -55,4 +64,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
 int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
 
+int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
+                             struct snd_kcontrol *kctl);
+
 #endif /* __USBMIXER_H */
index 9146cff..3d0f487 100644 (file)
@@ -40,6 +40,8 @@
 #include "mixer_quirks.h"
 #include "helper.h"
 
+extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+
 /*
  * Sound Blaster remote control configuration
  *
@@ -492,6 +494,69 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
        return err;
 }
 
+/* M-Audio FastTrack Ultra quirks */
+
+/* private_free callback */
+static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
+{
+       kfree(kctl->private_data);
+       kctl->private_data = NULL;
+}
+
+static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
+                                    int in, int out, const char *name)
+{
+       struct usb_mixer_elem_info *cval;
+       struct snd_kcontrol *kctl;
+
+       cval = kzalloc(sizeof(*cval), GFP_KERNEL);
+       if (!cval)
+               return -ENOMEM;
+
+       cval->id = 5;
+       cval->mixer = mixer;
+       cval->val_type = USB_MIXER_S16;
+       cval->channels = 1;
+       cval->control = out + 1;
+       cval->cmask = 1 << in;
+
+       kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
+       if (!kctl) {
+               kfree(cval);
+               return -ENOMEM;
+       }
+
+       snprintf(kctl->id.name, sizeof(kctl->id.name), name);
+       kctl->private_free = usb_mixer_elem_free;
+       return snd_usb_mixer_add_control(mixer, kctl);
+}
+
+static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
+{
+       char name[64];
+       int in, out, err;
+
+       for (out = 0; out < 8; out++) {
+               for (in = 0; in < 8; in++) {
+                       snprintf(name, sizeof(name),
+                                "AIn%d - Out%d Capture Volume", in  + 1, out + 1);
+                       err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
+                       if (err < 0)
+                               return err;
+               }
+
+               for (in = 8; in < 16; in++) {
+                       snprintf(name, sizeof(name),
+                                "DIn%d - Out%d Playback Volume", in - 7, out + 1);
+                       err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
+                       if (err < 0)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
 void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
                               unsigned char samplerate_id)
 {
@@ -533,6 +598,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
                                              snd_audigy2nx_proc_read);
                break;
 
+       case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
+       case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
+               err = snd_maudio_ftu_create_mixer(mixer);
+               break;
+
        case USB_ID(0x0b05, 0x1739):
        case USB_ID(0x0b05, 0x1743):
                err = snd_xonar_u1_controls_create(mixer);
index 78792a8..0b2ae8e 100644 (file)
@@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .data = & (const struct snd_usb_audio_quirk[]) {
                        {
                                .ifnum = 0,
-                               .type = QUIRK_IGNORE_INTERFACE
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
                        },
                        {
                                .ifnum = 1,
@@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .data = & (const struct snd_usb_audio_quirk[]) {
                        {
                                .ifnum = 0,
-                               .type = QUIRK_IGNORE_INTERFACE
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
                        },
                        {
                                .ifnum = 1,
index bd13d72..2e969cb 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/usb.h>
 #include <linux/usb/audio.h>
 
+#include <sound/control.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/pcm.h>
@@ -262,6 +263,20 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
        return 0;
 }
 
+/*
+ * Create a standard mixer for the specified interface.
+ */
+static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
+                                      struct usb_interface *iface,
+                                      struct usb_driver *driver,
+                                      const struct snd_usb_audio_quirk *quirk)
+{
+       if (quirk->ifnum < 0)
+               return 0;
+
+       return snd_usb_create_mixer(chip, quirk->ifnum, 0);
+}
+
 /*
  * audio-interface quirks
  *
@@ -294,7 +309,8 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
-               [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
+               [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
+               [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
        };
 
        if (quirk->type < QUIRK_TYPE_COUNT) {
index 32f2a97..1e79986 100644 (file)
@@ -84,6 +84,7 @@ enum quirk_type {
        QUIRK_AUDIO_FIXED_ENDPOINT,
        QUIRK_AUDIO_EDIROL_UAXX,
        QUIRK_AUDIO_ALIGN_TRANSFER,
+       QUIRK_AUDIO_STANDARD_MIXER,
 
        QUIRK_TYPE_COUNT
 };