Merge branch 'fix/asoc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Fri, 23 Sep 2011 13:26:37 +0000 (15:26 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 23 Sep 2011 13:26:37 +0000 (15:26 +0200)
29 files changed:
sound/aoa/fabrics/layout.c
sound/core/pcm_lib.c
sound/core/timer.c
sound/oss/pas2_pcm.c
sound/oss/pss.c
sound/pci/Kconfig
sound/pci/ac97/ac97_patch.c
sound/pci/asihpi/hpicmn.c
sound/pci/azt3328.c
sound/pci/fm801.c
sound/pci/hda/alc268_quirks.c
sound/pci/hda/alc269_quirks.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/rme9652/hdspm.c
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.h
sound/usb/caiaq/input.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/quirks-table.h
sound/usb/quirks.c

index 3fd1a7e..552b97a 100644 (file)
@@ -1073,10 +1073,10 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
        sdev->pcmid = -1;
        list_del(&ldev->list);
        layouts_list_items--;
+       kfree(ldev);
  outnodev:
        of_node_put(sound);
        layout_device = NULL;
-       kfree(ldev);
        return -ENODEV;
 }
 
index 86d0caf..62e90b8 100644 (file)
@@ -1761,6 +1761,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t avail = 0;
        long wait_time, tout;
 
+       init_waitqueue_entry(&wait, current);
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&runtime->tsleep, &wait);
+
        if (runtime->no_period_wakeup)
                wait_time = MAX_SCHEDULE_TIMEOUT;
        else {
@@ -1771,16 +1775,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                }
                wait_time = msecs_to_jiffies(wait_time * 1000);
        }
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&runtime->tsleep, &wait);
+
        for (;;) {
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
                }
+
+               /*
+                * We need to check if space became available already
+                * (and thus the wakeup happened already) first to close
+                * the race of space already having become available.
+                * This check must happen after been added to the waitqueue
+                * and having current state be INTERRUPTIBLE.
+                */
+               if (is_playback)
+                       avail = snd_pcm_playback_avail(runtime);
+               else
+                       avail = snd_pcm_capture_avail(runtime);
+               if (avail >= runtime->twake)
+                       break;
                snd_pcm_stream_unlock_irq(substream);
-               tout = schedule_timeout_interruptible(wait_time);
+
+               tout = schedule_timeout(wait_time);
+
                snd_pcm_stream_lock_irq(substream);
+               set_current_state(TASK_INTERRUPTIBLE);
                switch (runtime->status->state) {
                case SNDRV_PCM_STATE_SUSPENDED:
                        err = -ESTRPIPE;
@@ -1806,14 +1826,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                        err = -EIO;
                        break;
                }
-               if (is_playback)
-                       avail = snd_pcm_playback_avail(runtime);
-               else
-                       avail = snd_pcm_capture_avail(runtime);
-               if (avail >= runtime->twake)
-                       break;
        }
  _endloop:
+       set_current_state(TASK_RUNNING);
        remove_wait_queue(&runtime->tsleep, &wait);
        *availp = avail;
        return err;
index 7c1cbf0..67ebf1c 100644 (file)
@@ -328,6 +328,8 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                mutex_unlock(&register_mutex);
        } else {
                timer = timeri->timer;
+               if (snd_BUG_ON(!timer))
+                       goto out;
                /* wait, until the active callback is finished */
                spin_lock_irq(&timer->lock);
                while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
@@ -353,6 +355,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                }
                mutex_unlock(&register_mutex);
        }
+ out:
        if (timeri->private_free)
                timeri->private_free(timeri);
        kfree(timeri->owner);
@@ -531,6 +534,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
        if (err < 0)
                return err;
        timer = timeri->timer;
+       if (!timer)
+               return -EINVAL;
        spin_lock_irqsave(&timer->lock, flags);
        timeri->cticks = timeri->ticks;
        timeri->pticks = 0;
index 8f7d175..6f13ab4 100644 (file)
@@ -63,13 +63,13 @@ static int pcm_set_speed(int arg)
 
        if (pcm_channels & 2)
        {
-               foo = ((CLOCK_TICK_RATE / 2) + (arg / 2)) / arg;
-               arg = ((CLOCK_TICK_RATE / 2) + (foo / 2)) / foo;
+               foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg;
+               arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo;
        }
        else
        {
-               foo = (CLOCK_TICK_RATE + (arg / 2)) / arg;
-               arg = (CLOCK_TICK_RATE + (foo / 2)) / foo;
+               foo = (PIT_TICK_RATE + (arg / 2)) / arg;
+               arg = (PIT_TICK_RATE + (foo / 2)) / foo;
        }
 
        pcm_speed = arg;
index 9b800ce..2fc0624 100644 (file)
@@ -673,7 +673,8 @@ static void configure_nonsound_components(void)
 
        if (pss_cdrom_port == -1) {     /* If cdrom port enablation wasn't requested */
                printk(KERN_INFO "PSS: CDROM port not enabled.\n");
-       } else if (check_region(pss_cdrom_port, 2)) {
+       } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) {
+               pss_cdrom_port = -1;
                printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
        } else {
                set_io_base(devc, CONF_CDROM, pss_cdrom_port);
@@ -1232,7 +1233,8 @@ static void __exit cleanup_pss(void)
                if(pssmpu)
                        unload_pss_mpu(&cfg_mpu);
                unload_pss(&cfg);
-       }
+       } else if (pss_cdrom_port != -1)
+               release_region(pss_cdrom_port, 2);
 
        if(!pss_keep_settings)  /* Keep hardware settings if asked */
        {
index 50abf5b..8816804 100644 (file)
@@ -1,5 +1,10 @@
 # ALSA PCI drivers
 
+config SND_TEA575X
+       tristate
+       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
+       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
+
 menuconfig SND_PCI
        bool "PCI sound devices"
        depends on PCI
@@ -563,11 +568,6 @@ config SND_FM801_TEA575X_BOOL
          FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
          SF64-PCR) into the snd-fm801 driver.
 
-config SND_TEA575X
-       tristate
-       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
-       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
-
 source "sound/pci/hda/Kconfig"
 
 config SND_HDSP
index 200c9a1..a872d0a 100644 (file)
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = {
        0x103c0944, /* HP nc6220 */
        0x103c0934, /* HP nc8220 */
        0x103c006d, /* HP nx9105 */
+       0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
        0x17340088, /* FSC Scenic-W */
        0 /* end */
 };
index 65b7ca1..bd47521 100644 (file)
@@ -631,13 +631,12 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
        if (!p_cache)
                return NULL;
 
-       p_cache->p_info =
-               kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
+       p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count,
+                                 GFP_KERNEL);
        if (!p_cache->p_info) {
                kfree(p_cache);
                return NULL;
        }
-       memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
        p_cache->cache_size_in_bytes = size_in_bytes;
        p_cache->control_count = control_count;
        p_cache->p_cache = p_dsp_control_buffer;
index e4d76a2..579fc0d 100644 (file)
@@ -2625,16 +2625,19 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        int err;
 
        snd_azf3328_dbgcallenter();
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
+       if (dev >= SNDRV_CARDS) {
+               err = -ENODEV;
+               goto out;
+       }
        if (!enable[dev]) {
                dev++;
-               return -ENOENT;
+               err = -ENOENT;
+               goto out;
        }
 
        err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
        if (err < 0)
-               return err;
+               goto out;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
index f9123f0..32b02d9 100644 (file)
@@ -68,6 +68,7 @@ MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
 module_param_array(tea575x_tuner, int, NULL, 0444);
 MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only).");
 
+#define TUNER_DISABLED         (1<<3)
 #define TUNER_ONLY             (1<<4)
 #define TUNER_TYPE_MASK                (~TUNER_ONLY & 0xFFFF)
 
@@ -1150,7 +1151,8 @@ static int snd_fm801_free(struct fm801 *chip)
 
       __end_hw:
 #ifdef CONFIG_SND_FM801_TEA575X_BOOL
-       snd_tea575x_exit(&chip->tea);
+       if (!(chip->tea575x_tuner & TUNER_DISABLED))
+               snd_tea575x_exit(&chip->tea);
 #endif
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
@@ -1236,7 +1238,6 @@ static int __devinit snd_fm801_create(struct snd_card *card,
            (tea575x_tuner & TUNER_TYPE_MASK) < 4) {
                if (snd_tea575x_init(&chip->tea)) {
                        snd_printk(KERN_ERR "TEA575x radio not found\n");
-                       snd_fm801_free(chip);
                        return -ENODEV;
                }
        } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
@@ -1251,11 +1252,15 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                }
                if (tea575x_tuner == 4) {
                        snd_printk(KERN_ERR "TEA575x radio not found\n");
-                       snd_fm801_free(chip);
-                       return -ENODEV;
+                       chip->tea575x_tuner = TUNER_DISABLED;
                }
        }
-       strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card));
+       if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
+               strlcpy(chip->tea.card,
+                       snd_fm801_tea575x_gpios[(tea575x_tuner &
+                                                TUNER_TYPE_MASK) - 1].name,
+                       sizeof(chip->tea.card));
+       }
 #endif
 
        *rchip = chip;
index be58bf2..2e5876c 100644 (file)
@@ -476,8 +476,8 @@ static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
 
 static const struct alc_config_preset alc268_presets[] = {
        [ALC267_QUANTA_IL1] = {
-               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc267_quanta_il1_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -492,8 +492,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_3ST] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
                .dac_nids = alc268_dac_nids,
@@ -507,8 +507,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .input_mux = &alc268_capture_source,
        },
        [ALC268_TOSHIBA] = {
-               .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_toshiba_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -525,8 +525,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER] = {
-               .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -543,8 +543,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_DMIC] = {
-               .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -561,9 +561,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_ASPIRE_ONE] = {
-               .mixers = { alc268_acer_aspire_one_mixer,
-                           alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_aspire_one_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -579,8 +578,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_DELL] = {
-               .mixers = { alc268_dell_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_dell_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -596,8 +595,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ZEPTO] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -616,7 +615,8 @@ static const struct alc_config_preset alc268_presets[] = {
        },
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST] = {
-               .mixers = { alc268_test_mixer, alc268_capture_mixer },
+               .mixers = { alc268_test_mixer },
+               .cap_mixer = alc268_capture_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_volume_init_verbs,
                                alc268_beep_init_verbs },
index 14fdcf2..5ac0e21 100644 (file)
@@ -531,17 +531,10 @@ static const struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
        SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
index 3e7850c..f3aefef 100644 (file)
@@ -579,9 +579,13 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
                return -1;
        }
        recursive++;
-       for (i = 0; i < nums; i++)
+       for (i = 0; i < nums; i++) {
+               unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
+               if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
+                       continue;
                if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
                        return i;
+       }
        return -1;
 }
 EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
index 28ce17d..c34f730 100644 (file)
@@ -144,25 +144,17 @@ static int cea_sampling_frequencies[8] = {
        SNDRV_PCM_RATE_192000,  /* 7: 192000Hz */
 };
 
-static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
+static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
                                        int byte_index)
 {
        unsigned int val;
 
        val = snd_hda_codec_read(codec, nid, 0,
                                        AC_VERB_GET_HDMI_ELDD, byte_index);
-
 #ifdef BE_PARANOID
        printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
 #endif
-
-       if ((val & AC_ELDD_ELD_VALID) == 0) {
-               snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
-                                                               byte_index);
-               val = 0;
-       }
-
-       return val & AC_ELDD_ELD_DATA;
+       return val;
 }
 
 #define GRAB_BITS(buf, byte, lowbit, bits)             \
@@ -344,11 +336,26 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
        if (!buf)
                return -ENOMEM;
 
-       for (i = 0; i < size; i++)
-               buf[i] = hdmi_get_eld_byte(codec, nid, i);
+       for (i = 0; i < size; i++) {
+               unsigned int val = hdmi_get_eld_data(codec, nid, i);
+               if (!(val & AC_ELDD_ELD_VALID)) {
+                       if (!i) {
+                               snd_printd(KERN_INFO
+                                          "HDMI: invalid ELD data\n");
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       snd_printd(KERN_INFO
+                                 "HDMI: invalid ELD data byte %d\n", i);
+                       val = 0;
+               } else
+                       val &= AC_ELDD_ELD_DATA;
+               buf[i] = val;
+       }
 
        ret = hdmi_update_eld(eld, buf, size);
 
+error:
        kfree(buf);
        return ret;
 }
index 47d6ffc..c45f3e6 100644 (file)
@@ -375,7 +375,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
 static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int *idxp)
 {
-       int i;
+       int i, idx;
        hda_nid_t nid;
 
        nid = codec->start_nid;
@@ -384,9 +384,11 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                type = get_wcaps_type(get_wcaps(codec, nid));
                if (type != AC_WID_AUD_IN)
                        continue;
-               *idxp = snd_hda_get_conn_index(codec, nid, pin, false);
-               if (*idxp >= 0)
+               idx = snd_hda_get_conn_index(codec, nid, pin, false);
+               if (idx >= 0) {
+                       *idxp = idx;
                        return nid;
+               }
        }
        return 0;
 }
@@ -533,7 +535,7 @@ static int add_volume(struct hda_codec *codec, const char *name,
                      int index, unsigned int pval, int dir,
                      struct snd_kcontrol **kctlp)
 {
-       char tmp[32];
+       char tmp[44];
        struct snd_kcontrol_new knew =
                HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT);
        knew.private_value = pval;
index 502fc94..7696d05 100644 (file)
@@ -3348,6 +3348,8 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
 
 #define MAX_AUTO_DACS  5
 
+#define DAC_SLAVE_FLAG 0x8000  /* filled dac is a slave */
+
 /* fill analog DAC list from the widget tree */
 static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 {
@@ -3370,16 +3372,26 @@ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 /* fill pin_dac_pair list from the pin and dac list */
 static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
                              int num_pins, hda_nid_t *dacs, int *rest,
-                             struct pin_dac_pair *filled, int type)
+                             struct pin_dac_pair *filled, int nums, 
+                             int type)
 {
-       int i, nums;
+       int i, start = nums;
 
-       nums = 0;
-       for (i = 0; i < num_pins; i++) {
+       for (i = 0; i < num_pins; i++, nums++) {
                filled[nums].pin = pins[i];
                filled[nums].type = type;
                filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
-               nums++;
+               if (filled[nums].dac) 
+                       continue;
+               if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) {
+                       filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) {
+                       filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]);
        }
        return nums;
 }
@@ -3395,19 +3407,19 @@ static void cx_auto_parse_output(struct hda_codec *codec)
        rest = fill_cx_auto_dacs(codec, dacs);
        /* parse all analog output pins */
        nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
-                                 dacs, &rest, spec->dac_info,
-                                 AUTO_PIN_LINE_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_HP_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_SPEAKER_OUT);
+                         dacs, &rest, spec->dac_info, 0,
+                         AUTO_PIN_LINE_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_HP_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_SPEAKER_OUT);
        spec->dac_info_filled = nums;
        /* fill multiout struct */
        for (i = 0; i < nums; i++) {
                hda_nid_t dac = spec->dac_info[i].dac;
-               if (!dac)
+               if (!dac || (dac & DAC_SLAVE_FLAG))
                        continue;
                switch (spec->dac_info[i].type) {
                case AUTO_PIN_LINE_OUT:
@@ -3862,7 +3874,7 @@ static void cx_auto_parse_input(struct hda_codec *codec)
        }
        if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items)
                cx_auto_check_auto_mic(codec);
-       if (imux->num_items > 1 && !spec->auto_mic) {
+       if (imux->num_items > 1) {
                for (i = 1; i < imux->num_items; i++) {
                        if (spec->imux_info[i].adc != spec->imux_info[0].adc) {
                                spec->adc_switching = 1;
@@ -4035,6 +4047,8 @@ static void cx_auto_init_output(struct hda_codec *codec)
                nid = spec->dac_info[i].dac;
                if (!nid)
                        nid = spec->multiout.dac_nids[0];
+               else if (nid & DAC_SLAVE_FLAG)
+                       nid &= ~DAC_SLAVE_FLAG;
                select_connection(codec, spec->dac_info[i].pin, nid);
        }
        if (spec->auto_mute) {
@@ -4167,9 +4181,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
                             hda_nid_t pin, const char *name, int idx)
 {
        unsigned int caps;
-       caps = query_amp_caps(codec, dac, HDA_OUTPUT);
-       if (caps & AC_AMPCAP_NUM_STEPS)
-               return cx_auto_add_pb_volume(codec, dac, name, idx);
+       if (dac && !(dac & DAC_SLAVE_FLAG)) {
+               caps = query_amp_caps(codec, dac, HDA_OUTPUT);
+               if (caps & AC_AMPCAP_NUM_STEPS)
+                       return cx_auto_add_pb_volume(codec, dac, name, idx);
+       }
        caps = query_amp_caps(codec, pin, HDA_OUTPUT);
        if (caps & AC_AMPCAP_NUM_STEPS)
                return cx_auto_add_pb_volume(codec, pin, name, idx);
@@ -4191,8 +4207,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
        for (i = 0; i < spec->dac_info_filled; i++) {
                const char *label;
                int idx, type;
-               if (!spec->dac_info[i].dac)
-                       continue;
+               hda_nid_t dac = spec->dac_info[i].dac;
                type = spec->dac_info[i].type;
                if (type == AUTO_PIN_LINE_OUT)
                        type = spec->autocfg.line_out_type;
@@ -4211,7 +4226,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
                        idx = num_spk++;
                        break;
                }
-               err = try_add_pb_volume(codec, spec->dac_info[i].dac,
+               err = try_add_pb_volume(codec, dac,
                                        spec->dac_info[i].pin,
                                        label, idx);
                if (err < 0)
index e125c60..0503c99 100644 (file)
@@ -168,7 +168,7 @@ struct alc_spec {
        unsigned int auto_mic_valid_imux:1;     /* valid imux for auto-mic */
        unsigned int automute:1;        /* HP automute enabled */
        unsigned int detect_line:1;     /* Line-out detection enabled */
-       unsigned int automute_lines:1;  /* automute line-out as well */
+       unsigned int automute_lines:1;  /* automute line-out as well; NOP when automute_hp_lo isn't set */
        unsigned int automute_hp_lo:1;  /* both HP and LO available */
 
        /* other flags */
@@ -551,7 +551,7 @@ static void update_speakers(struct hda_codec *codec)
        if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
            spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
                return;
-       if (!spec->automute_lines || !spec->automute)
+       if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
                on = 0;
        else
                on = spec->jack_present;
@@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute)
-               return;
        spec->jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                             spec->autocfg.hp_pins);
+       if (!spec->automute)
+               return;
        update_speakers(codec);
 }
 
@@ -578,11 +578,11 @@ static void alc_line_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute || !spec->detect_line)
-               return;
        spec->line_jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                             spec->autocfg.line_out_pins);
+       if (!spec->automute || !spec->detect_line)
+               return;
        update_speakers(codec);
 }
 
@@ -803,7 +803,7 @@ static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
        unsigned int val;
        if (!spec->automute)
                val = 0;
-       else if (!spec->automute_lines)
+       else if (!spec->automute_hp_lo || !spec->automute_lines)
                val = 1;
        else
                val = 2;
@@ -824,7 +824,8 @@ static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
                spec->automute = 0;
                break;
        case 1:
-               if (spec->automute && !spec->automute_lines)
+               if (spec->automute &&
+                   (!spec->automute_hp_lo || !spec->automute_lines))
                        return 0;
                spec->automute = 1;
                spec->automute_lines = 0;
@@ -1784,6 +1785,7 @@ static const char * const alc_slave_vols[] = {
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
+       "PCM Playback Volume",
        NULL,
 };
 
@@ -1798,6 +1800,7 @@ static const char * const alc_slave_sws[] = {
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
+       "PCM Playback Switch",
        NULL,
 };
 
@@ -3081,16 +3084,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec)
 static void alc_auto_init_extra_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t pin;
+       hda_nid_t pin, dac;
 
        pin = spec->autocfg.hp_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
-                                                 spec->multiout.hp_nid);
+       if (pin) {
+               dac = spec->multiout.hp_nid;
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+       }
        pin = spec->autocfg.speaker_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
-                                       spec->multiout.extra_out_nid[0]);
+       if (pin) {
+               dac = spec->multiout.extra_out_nid[0];
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+       }
 }
 
 /*
@@ -4484,6 +4493,22 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec,
        spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
 }
 
+static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
+                                    const struct alc_fixup *fix, int action)
+{
+       int coef;
+
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       /* The digital-mic unit sends PDM (differential signal) instead of
+        * the standard PCM, thus you can't record a valid mono stream as is.
+        * Below is a workaround specific to ALC269 to control the dmic
+        * signal source as mono.
+        */
+       coef = alc_read_coef_idx(codec, 0x07);
+       alc_write_coef_idx(codec, 0x07, coef | 0x80);
+}
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4494,6 +4519,7 @@ enum {
        ALC275_FIXUP_SONY_HWEQ,
        ALC271_FIXUP_DMIC,
        ALC269_FIXUP_PCM_44K,
+       ALC269_FIXUP_STEREO_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -4556,10 +4582,19 @@ static const struct alc_fixup alc269_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc269_fixup_pcm_44k,
        },
+       [ALC269_FIXUP_STEREO_DMIC] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc269_fixup_stereo_dmic,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
+       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
index aa376b5..1b7c114 100644 (file)
@@ -673,6 +673,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
 static int stac_vrefout_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
 {
@@ -696,6 +697,7 @@ static int stac_vrefout_set(struct hda_codec *codec,
 
        return 1;
 }
+#endif
 
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
@@ -6571,6 +6573,7 @@ static const struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
        { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
        { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx},
        { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx},
        { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx},
        { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx},
index 84d8798..4ebfbd8 100644 (file)
@@ -2084,7 +2084,7 @@ static int via_auto_create_speaker_ctls(struct hda_codec *codec)
        struct via_spec *spec = codec->spec;
        struct nid_path *path;
        bool check_dac;
-       hda_nid_t pin, dac;
+       hda_nid_t pin, dac = 0;
        int err;
 
        pin = spec->autocfg.speaker_pins[0];
index 6edc67c..493e394 100644 (file)
@@ -1339,6 +1339,10 @@ static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
                break;
        case MADIface:
                freq_const = 131072000000000ULL;
+               break;
+       default:
+               snd_BUG();
+               return 0;
        }
 
        return div_u64(freq_const, period);
@@ -1356,16 +1360,19 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 
        switch (hdspm->io_type) {
        case MADIface:
-         n = 131072000000000ULL;  /* 125 MHz */
-         break;
+               n = 131072000000000ULL;  /* 125 MHz */
+               break;
        case MADI:
        case AES32:
-         n = 110069313433624ULL;  /* 105 MHz */
-         break;
+               n = 110069313433624ULL;  /* 105 MHz */
+               break;
        case RayDAT:
        case AIO:
-         n = 104857600000000ULL;  /* 100 MHz */
-         break;
+               n = 104857600000000ULL;  /* 100 MHz */
+               break;
+       default:
+               snd_BUG();
+               return;
        }
 
        n = div_u64(n, rate);
index d0d493c..2cf87f5 100644 (file)
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev)
 
        for (i = 0; i < N_URBS; i++) {
                usb_kill_urb(dev->data_urbs_in[i]);
-               usb_kill_urb(dev->data_urbs_out[i]);
+
+               if (test_bit(i, &dev->outurb_active_mask))
+                       usb_kill_urb(dev->data_urbs_out[i]);
        }
+
+       dev->outurb_active_mask = 0;
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
@@ -612,8 +616,9 @@ static void read_completed(struct urb *urb)
 {
        struct snd_usb_caiaq_cb_info *info = urb->context;
        struct snd_usb_caiaqdev *dev;
-       struct urb *out;
-       int frame, len, send_it = 0, outframe = 0;
+       struct urb *out = NULL;
+       int i, frame, len, send_it = 0, outframe = 0;
+       size_t offset = 0;
 
        if (urb->status || !info)
                return;
@@ -623,7 +628,17 @@ static void read_completed(struct urb *urb)
        if (!dev->streaming)
                return;
 
-       out = dev->data_urbs_out[info->index];
+       /* find an unused output urb that is unused */
+       for (i = 0; i < N_URBS; i++)
+               if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) {
+                       out = dev->data_urbs_out[i];
+                       break;
+               }
+
+       if (!out) {
+               log("Unable to find an output urb to use\n");
+               goto requeue;
+       }
 
        /* read the recently received packet and send back one which has
         * the same layout */
@@ -634,7 +649,8 @@ static void read_completed(struct urb *urb)
                len = urb->iso_frame_desc[outframe].actual_length;
                out->iso_frame_desc[outframe].length = len;
                out->iso_frame_desc[outframe].actual_length = 0;
-               out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+               out->iso_frame_desc[outframe].offset = offset;
+               offset += len;
 
                if (len > 0) {
                        spin_lock(&dev->spinlock);
@@ -650,11 +666,15 @@ static void read_completed(struct urb *urb)
        }
 
        if (send_it) {
-               out->number_of_packets = FRAMES_PER_URB;
+               out->number_of_packets = outframe;
                out->transfer_flags = URB_ISO_ASAP;
                usb_submit_urb(out, GFP_ATOMIC);
+       } else {
+               struct snd_usb_caiaq_cb_info *oinfo = out->context;
+               clear_bit(oinfo->index, &dev->outurb_active_mask);
        }
 
+requeue:
        /* re-submit inbound urb */
        for (frame = 0; frame < FRAMES_PER_URB; frame++) {
                urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
@@ -676,6 +696,8 @@ static void write_completed(struct urb *urb)
                dev->output_running = 1;
                wake_up(&dev->prepare_wait_queue);
        }
+
+       clear_bit(info->index, &dev->outurb_active_mask);
 }
 
 static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
@@ -827,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        if (!dev->data_cb_info)
                return -ENOMEM;
 
+       dev->outurb_active_mask = 0;
+       BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8));
+
        for (i = 0; i < N_URBS; i++) {
                dev->data_cb_info[i].dev = dev;
                dev->data_cb_info[i].index = i;
index b2b3101..3f9c633 100644 (file)
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev {
        int input_panic, output_panic, warned;
        char *audio_in_buf, *audio_out_buf;
        unsigned int samplerates, bpp;
+       unsigned long outurb_active_mask;
 
        struct snd_pcm_substream *sub_playback[MAX_STREAMS];
        struct snd_pcm_substream *sub_capture[MAX_STREAMS];
index 4432ef7..a213813 100644 (file)
@@ -30,7 +30,7 @@ static unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
 static unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
                                         KEY_5, KEY_6, KEY_7 };
 static unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
-                                        KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
+                                        KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 };
 
 static unsigned short keycode_kore[] = {
        KEY_FN_F1,      /* "menu"               */
index 781d9e6..ed120ca 100644 (file)
@@ -532,6 +532,7 @@ snd_usb_audio_probe(struct usb_device *dev,
  __error:
        if (chip && !chip->num_interfaces)
                snd_card_free(chip->card);
+       chip->probing = 0;
        mutex_unlock(&register_mutex);
  __err_val:
        return NULL;
index 7c0d21e..7d46e48 100644 (file)
@@ -352,7 +352,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
                if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
-                   ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
+                   ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
                        snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
                                   dev->devnum, iface_no, altno);
                        continue;
index c22fa76..cdd19d7 100644 (file)
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,
        if (p && p->dB) {
                cval->dBmin = p->dB->min;
                cval->dBmax = p->dB->max;
+               cval->initialized = 1;
        }
 }
 
@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                " Switch" : " Volume");
                if (control == UAC_FU_VOLUME) {
                        check_mapped_dB(map, cval);
-                       if (cval->dBmin < cval->dBmax) {
+                       if (cval->dBmin < cval->dBmax || !cval->initialized) {
                                kctl->tlv.c = mixer_vol_tlv;
                                kctl->vd[0].access |= 
                                        SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1191,6 +1192,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 
        if (state->mixer->protocol == UAC_VERSION_1) {
                csize = hdr->bControlSize;
+               if (!csize) {
+                       snd_printdd(KERN_ERR "usbaudio: unit %u: "
+                                   "invalid bControlSize == 0\n", unitid);
+                       return -EINVAL;
+               }
                channels = (hdr->bLength - 7) / csize - 1;
                bmaControls = hdr->bmaControls;
        } else {
@@ -1934,15 +1940,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        struct mixer_build state;
        int err;
        const struct usbmix_ctl_map *map;
-       struct usb_host_interface *hostif;
        void *p;
 
-       hostif = mixer->chip->ctrl_intf;
        memset(&state, 0, sizeof(state));
        state.chip = mixer->chip;
        state.mixer = mixer;
-       state.buffer = hostif->extra;
-       state.buflen = hostif->extralen;
+       state.buffer = mixer->hostif->extra;
+       state.buflen = mixer->hostif->extralen;
 
        /* check the mapping table */
        for (map = usbmix_ctl_maps; map->id; map++) {
@@ -1955,7 +1959,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        }
 
        p = NULL;
-       while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
+       while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
+                                           p, UAC_OUTPUT_TERMINAL)) != NULL) {
                if (mixer->protocol == UAC_VERSION_1) {
                        struct uac1_output_terminal_descriptor *desc = p;
 
@@ -2162,17 +2167,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
 /* create the handler for the optional status interrupt endpoint */
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 {
-       struct usb_host_interface *hostif;
        struct usb_endpoint_descriptor *ep;
        void *transfer_buffer;
        int buffer_length;
        unsigned int epnum;
 
-       hostif = mixer->chip->ctrl_intf;
        /* we need one interrupt input endpoint */
-       if (get_iface_desc(hostif)->bNumEndpoints < 1)
+       if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1)
                return 0;
-       ep = get_endpoint(hostif, 0);
+       ep = get_endpoint(mixer->hostif, 0);
        if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
                return 0;
 
@@ -2202,7 +2205,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        };
        struct usb_mixer_interface *mixer;
        struct snd_info_entry *entry;
-       struct usb_host_interface *host_iface;
        int err;
 
        strcpy(chip->card->mixername, "USB Mixer");
@@ -2219,8 +2221,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                return -ENOMEM;
        }
 
-       host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-       switch (get_iface_desc(host_iface)->bInterfaceProtocol) {
+       mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
+       switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) {
        case UAC_VERSION_1:
        default:
                mixer->protocol = UAC_VERSION_1;
index ae1a14d..81b2d8a 100644 (file)
@@ -3,6 +3,7 @@
 
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
+       struct usb_host_interface *hostif;
        struct list_head list;
        unsigned int ignore_ctl_error;
        struct urb *urb;
index dba0b7f..a42e3ef 100644 (file)
@@ -1707,6 +1707,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE(0x0582, 0x0130),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "BOSS", */
+               /* .product_name = "MICRO BR-80", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Guillemot devices */
 {
@@ -2417,6 +2451,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .idProduct = 0x1020,
 },
 
+/* KeithMcMillen Stringport */
+{
+       USB_DEVICE(0x1f38, 0x0001),
+       .bInterfaceClass = USB_CLASS_AUDIO,
+},
+
 /* Miditech devices */
 {
        USB_DEVICE(0x4752, 0x0011),
index 77762c9..81e07d8 100644 (file)
@@ -426,7 +426,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
  */
 static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 {
-       int err, reg;
+       int err  = 0, reg;
        int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
 
        for (reg = 0; reg < ARRAY_SIZE(val); reg++) {