diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/oss/pcm_oss.c | 12 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 5 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 2 | ||||
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 3 | ||||
-rw-r--r-- | sound/core/seq/seq_clientmgr.h | 1 | ||||
-rw-r--r-- | sound/core/seq/seq_queue.c | 4 | ||||
-rw-r--r-- | sound/core/seq/seq_timer.c | 13 | ||||
-rw-r--r-- | sound/core/seq/seq_timer.h | 2 | ||||
-rw-r--r-- | sound/drivers/dummy.c | 2 | ||||
-rw-r--r-- | sound/isa/gus/gus_dma.c | 5 | ||||
-rw-r--r-- | sound/mips/hal2.c | 2 | ||||
-rw-r--r-- | sound/mips/sgio2audio.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 132 | ||||
-rw-r--r-- | sound/pci/ice1712/prodigy_hifi.c | 131 | ||||
-rw-r--r-- | sound/pci/korg1212/korg1212.c | 1 | ||||
-rw-r--r-- | sound/sound_core.c | 42 | ||||
-rw-r--r-- | sound/usb/card.c | 21 | ||||
-rw-r--r-- | sound/usb/mixer.c | 8 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 82 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 48 |
22 files changed, 410 insertions, 110 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index c2db7e905f7d..e8b19876c420 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -186,7 +186,7 @@ static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, { int changed; changed = snd_mask_refine(hw_param_mask(params, var), val); - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -233,7 +233,7 @@ static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, val, open); else return -EINVAL; - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -294,7 +294,7 @@ static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, val, open); else return -EINVAL; - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -499,7 +499,7 @@ static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, } } else return -EINVAL; - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -539,7 +539,7 @@ static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, { int changed; changed = snd_interval_setinteger(hw_param_interval(params, var)); - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -842,7 +842,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, if (!(mutex_trylock(&runtime->oss.params_lock))) return -EAGAIN; } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) - return -EINTR; + return -ERESTARTSYS; sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL); sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index db7894bb028c..a83152e7d387 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -560,7 +560,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, { u_int64_t n = (u_int64_t) a * b; if (c == 0) { - snd_BUG_ON(!n); *r = 0; return UINT_MAX; } @@ -1603,7 +1602,7 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, changed = snd_interval_refine_first(hw_param_interval(params, var)); else return -EINVAL; - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } @@ -1649,7 +1648,7 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, changed = snd_interval_refine_last(hw_param_interval(params, var)); else return -EINVAL; - if (changed) { + if (changed > 0) { params->cmask |= 1 << var; params->rmask |= 1 << var; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f08772568c17..484a18d96371 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3446,7 +3446,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area) { - struct snd_pcm_runtime *runtime = substream->runtime;; + struct snd_pcm_runtime *runtime = substream->runtime; area->vm_page_prot = pgprot_noncached(area->vm_page_prot); return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 6e22eea72654..d01913404581 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -221,6 +221,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) rwlock_init(&client->ports_lock); mutex_init(&client->ports_mutex); INIT_LIST_HEAD(&client->ports_list_head); + mutex_init(&client->ioctl_mutex); /* find free slot in the client table */ spin_lock_irqsave(&clients_lock, flags); @@ -2130,7 +2131,9 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, return -EFAULT; } + mutex_lock(&client->ioctl_mutex); err = handler->func(client, &buf); + mutex_unlock(&client->ioctl_mutex); if (err >= 0) { /* Some commands includes a bug in 'dir' field. */ if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT || diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h index c6614254ef8a..0611e1e0ed5b 100644 --- a/sound/core/seq/seq_clientmgr.h +++ b/sound/core/seq/seq_clientmgr.h @@ -61,6 +61,7 @@ struct snd_seq_client { struct list_head ports_list_head; rwlock_t ports_lock; struct mutex ports_mutex; + struct mutex ioctl_mutex; int convert32; /* convert 32->64bit */ /* output pool */ diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 79e0c5604ef8..0428e9061b47 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -497,9 +497,7 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client, return -EPERM; } - result = snd_seq_timer_set_tempo(q->timer, info->tempo); - if (result >= 0) - result = snd_seq_timer_set_ppq(q->timer, info->ppq); + result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq); if (result >= 0 && info->skew_base > 0) result = snd_seq_timer_set_skew(q->timer, info->skew_value, info->skew_base); diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index b80985fbc334..23167578231f 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -191,14 +191,15 @@ int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo) return 0; } -/* set current ppq */ -int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq) +/* set current tempo and ppq in a shot */ +int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq) { + int changed; unsigned long flags; if (snd_BUG_ON(!tmr)) return -EINVAL; - if (ppq <= 0) + if (tempo <= 0 || ppq <= 0) return -EINVAL; spin_lock_irqsave(&tmr->lock, flags); if (tmr->running && (ppq != tmr->ppq)) { @@ -208,9 +209,11 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq) pr_debug("ALSA: seq: cannot change ppq of a running timer\n"); return -EBUSY; } - + changed = (tempo != tmr->tempo) || (ppq != tmr->ppq); + tmr->tempo = tempo; tmr->ppq = ppq; - snd_seq_timer_set_tick_resolution(tmr); + if (changed) + snd_seq_timer_set_tick_resolution(tmr); spin_unlock_irqrestore(&tmr->lock, flags); return 0; } diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h index 9506b661fe5b..62f390671096 100644 --- a/sound/core/seq/seq_timer.h +++ b/sound/core/seq/seq_timer.h @@ -131,7 +131,7 @@ int snd_seq_timer_stop(struct snd_seq_timer *tmr); int snd_seq_timer_start(struct snd_seq_timer *tmr); int snd_seq_timer_continue(struct snd_seq_timer *tmr); int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo); -int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq); +int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq); int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position); int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position); int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 7b2b1f766b00..69db45bc0197 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -830,7 +830,7 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info) { - const char *const names[] = { "None", "CD Player" }; + static const char *const names[] = { "None", "CD Player" }; return snd_ctl_enum_info(info, 1, 2, names); } diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index 36c27c832360..7f95f452f106 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -201,10 +201,9 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, struct snd_gf1_dma_block *block; block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); - if (block == NULL) { - snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); + if (!block) return -ENOMEM; - } + *block = *__block; block->next = NULL; diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 37d378a26a50..c8904e732aaa 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -814,7 +814,7 @@ static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip) struct hpc3_regs *hpc3 = hpc3c0; int err; - hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL); + hal2 = kzalloc(sizeof(*hal2), GFP_KERNEL); if (!hal2) return -ENOMEM; diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 71c942162c25..9fb68b35de5a 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -840,7 +840,7 @@ static int snd_sgio2audio_create(struct snd_card *card, if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT)) return -ENOENT; - chip = kzalloc(sizeof(struct snd_sgio2audio), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 7f3b5ed81995..f7a492c382d9 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -88,7 +88,6 @@ config SND_HDA_PATCH_LOADER config SND_HDA_CODEC_REALTEK tristate "Build Realtek HD-audio codec support" select SND_HDA_GENERIC - select INPUT help Say Y or M here to include Realtek HD-audio codec support in snd-hda-intel driver, such as ALC880. diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 80bbadc83721..d6e079f4ec09 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -408,6 +408,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ /* codec SSID */ + SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8fd2d9c62c96..0004e282a837 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3166,6 +3166,93 @@ static void alc256_shutup(struct hda_codec *codec) snd_hda_shutup_pins(codec); } +static void alc225_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp1_pin_sense, hp2_pin_sense; + + if (!hp_pin) + return; + + msleep(30); + + hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin); + hp2_pin_sense = snd_hda_jack_detect(codec, 0x16); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(2); + + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ + + if (hp1_pin_sense) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + if (hp2_pin_sense) + snd_hda_codec_write(codec, 0x16, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(85); + + if (hp1_pin_sense) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + if (hp2_pin_sense) + snd_hda_codec_write(codec, 0x16, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(100); + + alc_update_coef_idx(codec, 0x4a, 3 << 10, 0); + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ +} + +static void alc225_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp1_pin_sense, hp2_pin_sense; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + /* 3k pull low control for Headset jack. */ + alc_update_coef_idx(codec, 0x4a, 0, 3 << 10); + + hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin); + hp2_pin_sense = snd_hda_jack_detect(codec, 0x16); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(2); + + if (hp1_pin_sense) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + if (hp2_pin_sense) + snd_hda_codec_write(codec, 0x16, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(85); + + if (hp1_pin_sense) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + if (hp2_pin_sense) + snd_hda_codec_write(codec, 0x16, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + if (hp1_pin_sense || hp2_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); +} + static void alc_default_init(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -3723,6 +3810,7 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, } } +#if IS_REACHABLE(INPUT) static void gpio2_mic_hotkey_event(struct hda_codec *codec, struct hda_jack_callback *event) { @@ -3855,6 +3943,10 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, spec->kb_dev = NULL; } } +#else /* INPUT */ +#define alc280_fixup_hp_gpio2_mic_hotkey NULL +#define alc233_fixup_lenovo_line2_mic_hotkey NULL +#endif /* INPUT */ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -3994,8 +4086,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) case 0x10ec0668: alc_process_coef_fw(codec, coef0668); break; + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: alc_process_coef_fw(codec, coef0225); break; @@ -4117,8 +4212,11 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, alc_process_coef_fw(codec, coef0688); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: alc_process_coef_fw(codec, alc225_pre_hsmode); alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10); @@ -4189,8 +4287,11 @@ static void alc_headset_mode_default(struct hda_codec *codec) }; switch (codec->core.vendor_id) { + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: alc_process_coef_fw(codec, alc225_pre_hsmode); alc_process_coef_fw(codec, coef0225); @@ -4332,8 +4433,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0668: alc_process_coef_fw(codec, coef0688); break; + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: val = alc_read_coef_idx(codec, 0x45); if (val & (1 << 9)) @@ -4436,8 +4540,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0668: alc_process_coef_fw(codec, coef0688); break; + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: alc_process_coef_fw(codec, coef0225); break; @@ -4566,9 +4673,18 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0xbe); is_ctia = (val & 0x1c02) == 0x1c02; break; + case 0x10ec0215: case 0x10ec0225: + case 0x10ec0285: case 0x10ec0295: + case 0x10ec0289: case 0x10ec0299: + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + msleep(80); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + alc_process_coef_fw(codec, alc225_pre_hsmode); alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000); val = alc_read_coef_idx(codec, 0x45); @@ -4588,6 +4704,12 @@ static void alc_determine_headset_type(struct hda_codec *codec) alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6); alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4); alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); + + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + msleep(80); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); break; case 0x10ec0867: is_ctia = true; @@ -6196,6 +6318,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), + SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -6919,16 +7042,17 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0285: case 0x10ec0289: spec->codec_variant = ALC269_TYPE_ALC215; + spec->shutup = alc225_shutup; + spec->init_hook = alc225_init; spec->gen.mixer_nid = 0; break; case 0x10ec0225: case 0x10ec0295: - spec->codec_variant = ALC269_TYPE_ALC225; - spec->gen.mixer_nid = 0; /* no loopback on ALC225 ALC295 */ - break; case 0x10ec0299: spec->codec_variant = ALC269_TYPE_ALC225; - spec->gen.mixer_nid = 0; /* no loopback on ALC299 */ + spec->shutup = alc225_shutup; + spec->init_hook = alc225_init; + spec->gen.mixer_nid = 0; /* no loopback on ALC225, ALC295 and ALC299 */ break; case 0x10ec0234: case 0x10ec0274: diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 2697402b5195..8dabd4d0211d 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -965,13 +965,32 @@ static int prodigy_hd2_add_controls(struct snd_ice1712 *ice) return 0; } +static void wm8766_init(struct snd_ice1712 *ice) +{ + static unsigned short wm8766_inits[] = { + WM8766_RESET, 0x0000, + WM8766_DAC_CTRL, 0x0120, + WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */ + WM8766_DAC_CTRL2, 0x0001, + WM8766_DAC_CTRL3, 0x0080, + WM8766_LDA1, 0x0100, + WM8766_LDA2, 0x0100, + WM8766_LDA3, 0x0100, + WM8766_RDA1, 0x0100, + WM8766_RDA2, 0x0100, + WM8766_RDA3, 0x0100, + WM8766_MUTE1, 0x0000, + WM8766_MUTE2, 0x0000, + }; + unsigned int i; -/* - * initialize the chip - */ -static int prodigy_hifi_init(struct snd_ice1712 *ice) + for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2) + wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]); +} + +static void wm8776_init(struct snd_ice1712 *ice) { - static unsigned short wm_inits[] = { + static unsigned short wm8776_inits[] = { /* These come first to reduce init pop noise */ WM_ADC_MUX, 0x0003, /* ADC mute */ /* 0x00c0 replaced by 0x0003 */ @@ -982,7 +1001,76 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice) WM_POWERDOWN, 0x0008, /* All power-up except HP */ WM_RESET, 0x0000, /* reset */ }; - static unsigned short wm_inits2[] = { + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2) + wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]); +} + +#ifdef CONFIG_PM_SLEEP +static int prodigy_hifi_resume(struct snd_ice1712 *ice) +{ + static unsigned short wm8776_reinit_registers[] = { + WM_MASTER_CTRL, + WM_DAC_INT, + WM_ADC_INT, + WM_OUT_MUX, + WM_HP_ATTEN_L, + WM_HP_ATTEN_R, + WM_PHASE_SWAP, + WM_DAC_CTRL2, + WM_ADC_ATTEN_L, + WM_ADC_ATTEN_R, + WM_ALC_CTRL1, + WM_ALC_CTRL2, + WM_ALC_CTRL3, + WM_NOISE_GATE, + WM_ADC_MUX, + /* no DAC attenuation here */ + }; + struct prodigy_hifi_spec *spec = ice->spec; + int i, ch; + + mutex_lock(&ice->gpio_mutex); + + /* reinitialize WM8776 and re-apply old register values */ + wm8776_init(ice); + schedule_timeout_uninterruptible(1); + for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++) + wm_put(ice, wm8776_reinit_registers[i], + wm_get(ice, wm8776_reinit_registers[i])); + + /* reinitialize WM8766 and re-apply volumes for all DACs */ + wm8766_init(ice); + for (ch = 0; ch < 2; ch++) { + wm_set_vol(ice, WM_DAC_ATTEN_L + ch, + spec->vol[2 + ch], spec->master[ch]); + + wm8766_set_vol(ice, WM8766_LDA1 + ch, + spec->vol[0 + ch], spec->master[ch]); + + wm8766_set_vol(ice, WM8766_LDA2 + ch, + spec->vol[4 + ch], spec->master[ch]); + + wm8766_set_vol(ice, WM8766_LDA3 + ch, + spec->vol[6 + ch], spec->master[ch]); + } + + /* unmute WM8776 DAC */ + wm_put(ice, WM_DAC_MUTE, 0x00); + wm_put(ice, WM_DAC_CTRL1, 0x90); + + mutex_unlock(&ice->gpio_mutex); + return 0; +} +#endif + +/* + * initialize the chip + */ +static int prodigy_hifi_init(struct snd_ice1712 *ice) +{ + static unsigned short wm8776_defaults[] = { WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ @@ -1010,22 +1098,6 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice) WM_DAC_MUTE, 0x0000, /* DAC unmute */ WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ }; - static unsigned short wm8766_inits[] = { - WM8766_RESET, 0x0000, - WM8766_DAC_CTRL, 0x0120, - WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */ - WM8766_DAC_CTRL2, 0x0001, - WM8766_DAC_CTRL3, 0x0080, - WM8766_LDA1, 0x0100, - WM8766_LDA2, 0x0100, - WM8766_LDA3, 0x0100, - WM8766_RDA1, 0x0100, - WM8766_RDA2, 0x0100, - WM8766_RDA3, 0x0100, - WM8766_MUTE1, 0x0000, - WM8766_MUTE2, 0x0000, - }; - struct prodigy_hifi_spec *spec; unsigned int i; @@ -1052,16 +1124,17 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice) ice->spec = spec; /* initialize WM8776 codec */ - for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) - wm_put(ice, wm_inits[i], wm_inits[i+1]); + wm8776_init(ice); schedule_timeout_uninterruptible(1); - for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) - wm_put(ice, wm_inits2[i], wm_inits2[i+1]); + for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2) + wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]); - /* initialize WM8766 codec */ - for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2) - wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]); + wm8766_init(ice); +#ifdef CONFIG_PM_SLEEP + ice->pm_resume = &prodigy_hifi_resume; + ice->pm_suspend_enabled = 1; +#endif return 0; } diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index c7b007164c99..4206ba44d8bb 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2348,7 +2348,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); if (err < 0) { - release_firmware(dsp_code); snd_printk(KERN_ERR "firmware not available\n"); snd_korg1212_free(korg1212); return err; diff --git a/sound/sound_core.c b/sound/sound_core.c index 99b73c675743..b4efb22db561 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -119,13 +119,6 @@ struct sound_unit char name[32]; }; -#ifdef CONFIG_SOUND_MSNDCLAS -extern int msnd_classic_init(void); -#endif -#ifdef CONFIG_SOUND_MSNDPIN -extern int msnd_pinnacle_init(void); -#endif - /* * By default, OSS sound_core claims full legacy minor range (0-255) * of SOUND_MAJOR to trap open attempts to any sound minor and @@ -452,26 +445,6 @@ int register_sound_mixer(const struct file_operations *fops, int dev) EXPORT_SYMBOL(register_sound_mixer); -/** - * register_sound_midi - register a midi device - * @fops: File operations for the driver - * @dev: Unit number to allocate - * - * Allocate a midi device. Unit is the number of the midi device requested. - * Pass -1 to request the next free midi unit. - * - * Return: On success, the allocated number is returned. On failure, - * a negative error code is returned. - */ - -int register_sound_midi(const struct file_operations *fops, int dev) -{ - return sound_insert_unit(&chains[2], fops, dev, 2, 130, - "midi", S_IRUSR | S_IWUSR, NULL); -} - -EXPORT_SYMBOL(register_sound_midi); - /* * DSP's are registered as a triple. Register only one and cheat * in open - see below. @@ -533,21 +506,6 @@ void unregister_sound_mixer(int unit) EXPORT_SYMBOL(unregister_sound_mixer); /** - * unregister_sound_midi - unregister a midi device - * @unit: unit number to allocate - * - * Release a sound device that was allocated with register_sound_midi(). - * The unit passed is the return value from the register function. - */ - -void unregister_sound_midi(int unit) -{ - sound_remove_unit(&chains[2], unit); -} - -EXPORT_SYMBOL(unregister_sound_midi); - -/** * unregister_sound_dsp - unregister a DSP device * @unit: unit number to allocate * diff --git a/sound/usb/card.c b/sound/usb/card.c index 23d1d23aefec..8018d56cfecc 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -585,15 +585,24 @@ static int usb_audio_probe(struct usb_interface *intf, * now look for an empty slot and create a new card instance */ for (i = 0; i < SNDRV_CARDS; i++) - if (enable[i] && ! usb_chip[i] && + if (!usb_chip[i] && (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { - err = snd_usb_audio_create(intf, dev, i, quirk, - id, &chip); - if (err < 0) + if (enable[i]) { + err = snd_usb_audio_create(intf, dev, i, quirk, + id, &chip); + if (err < 0) + goto __error; + chip->pm_intf = intf; + break; + } else if (vid[i] != -1 || pid[i] != -1) { + dev_info(&dev->dev, + "device (%04x:%04x) is disabled\n", + USB_ID_VENDOR(id), + USB_ID_PRODUCT(id)); + err = -ENOENT; goto __error; - chip->pm_intf = intf; - break; + } } if (!chip) { dev_err(&dev->dev, "no available usb audio device\n"); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 2b4ceda36291..9afb8ab524c7 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -656,10 +656,14 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm unsigned char *name, int maxlen, int term_only) { struct iterm_name_combo *names; + int len; - if (iterm->name) - return snd_usb_copy_string_desc(state, iterm->name, + if (iterm->name) { + len = snd_usb_copy_string_desc(state, iterm->name, name, maxlen); + if (len) + return len; + } /* virtual type - not a real terminal */ if (iterm->type >> 16) { diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e1e7ce9ab217..e6359d341878 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -27,6 +27,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/hid.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/usb.h> @@ -1721,6 +1722,83 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer) return 0; } +/* Creative Sound Blaster E1 */ + +static int snd_soundblaster_e1_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = kcontrol->private_value; + return 0; +} + +static int snd_soundblaster_e1_switch_update(struct usb_mixer_interface *mixer, + unsigned char state) +{ + struct snd_usb_audio *chip = mixer->chip; + int err; + unsigned char buff[2]; + + buff[0] = 0x02; + buff[1] = state ? 0x02 : 0x00; + + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + 0x0202, 3, buff, 2); + snd_usb_unlock_shutdown(chip); + return err; +} + +static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); + unsigned char value = !!ucontrol->value.integer.value[0]; + int err; + + if (kcontrol->private_value == value) + return 0; + kcontrol->private_value = value; + err = snd_soundblaster_e1_switch_update(list->mixer, value); + return err < 0 ? err : 1; +} + +static int snd_soundblaster_e1_switch_resume(struct usb_mixer_elem_list *list) +{ + return snd_soundblaster_e1_switch_update(list->mixer, + list->kctl->private_value); +} + +static int snd_soundblaster_e1_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const texts[2] = { + "Mic", "Aux" + }; + + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); +} + +static struct snd_kcontrol_new snd_soundblaster_e1_input_switch = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Input Source", + .info = snd_soundblaster_e1_switch_info, + .get = snd_soundblaster_e1_switch_get, + .put = snd_soundblaster_e1_switch_put, + .private_value = 0, +}; + +static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer) +{ + return add_single_ctl_with_resume(mixer, 0, + snd_soundblaster_e1_switch_resume, + &snd_soundblaster_e1_input_switch, + NULL); +} + int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1802,6 +1880,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x1235, 0x800c): /* Focusrite Scarlett 18i20 */ err = snd_scarlett_controls_create(mixer); break; + + case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ + err = snd_soundblaster_e1_switch_create(mixer); + break; } return err; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 8a59d4782a0f..50252046b01d 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3277,4 +3277,52 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } }, +{ + /* + * Nura's first gen headphones use Cambridge Silicon Radio's vendor + * ID, but it looks like the product ID actually is only for Nura. + * The capture interface does not work at all (even on Windows), + * and only the 48 kHz sample rate works for the playback interface. + */ + USB_DEVICE(0x0a12, 0x1243), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_STANDARD_MIXER, + }, + /* Capture */ + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE, + }, + /* Playback */ + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 2, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = UAC_EP_CS_ATTR_FILL_MAX | + UAC_EP_CS_ATTR_SAMPLE_RATE, + .endpoint = 0x03, + .ep_attr = USB_ENDPOINT_XFER_ISOC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + } + } +}, + #undef USB_DEVICE_VENDOR_SPEC |