diff options
Diffstat (limited to 'sound')
52 files changed, 2111 insertions, 5993 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index dc2a44048c8..978fe1a8e9f 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -989,7 +989,6 @@ struct user_element { void *tlv_data; /* TLV data */ unsigned long tlv_data_size; /* TLV data size */ void *priv_data; /* private data (like strings for enumerated type) */ - unsigned long priv_data_size; /* size of private data in bytes */ }; static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, @@ -1001,6 +1000,28 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, return 0; } +static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct user_element *ue = kcontrol->private_data; + const char *names; + unsigned int item; + + item = uinfo->value.enumerated.item; + + *uinfo = ue->info; + + item = min(item, uinfo->value.enumerated.items - 1); + uinfo->value.enumerated.item = item; + + names = ue->priv_data; + for (; item > 0; --item) + names += strlen(names) + 1; + strcpy(uinfo->value.enumerated.name, names); + + return 0; +} + static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1055,11 +1076,46 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, return change; } +static int snd_ctl_elem_init_enum_names(struct user_element *ue) +{ + char *names, *p; + size_t buf_len, name_len; + unsigned int i; + + if (ue->info.value.enumerated.names_length > 64 * 1024) + return -EINVAL; + + names = memdup_user( + (const void __user *)ue->info.value.enumerated.names_ptr, + ue->info.value.enumerated.names_length); + if (IS_ERR(names)) + return PTR_ERR(names); + + /* check that there are enough valid names */ + buf_len = ue->info.value.enumerated.names_length; + p = names; + for (i = 0; i < ue->info.value.enumerated.items; ++i) { + name_len = strnlen(p, buf_len); + if (name_len == 0 || name_len >= 64 || name_len == buf_len) { + kfree(names); + return -EINVAL; + } + p += name_len + 1; + buf_len -= name_len + 1; + } + + ue->priv_data = names; + ue->info.value.enumerated.names_ptr = 0; + + return 0; +} + static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) { struct user_element *ue = kcontrol->private_data; - if (ue->tlv_data) - kfree(ue->tlv_data); + + kfree(ue->tlv_data); + kfree(ue->priv_data); kfree(ue); } @@ -1101,7 +1157,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, memcpy(&kctl.id, &info->id, sizeof(info->id)); kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; - kctl.info = snd_ctl_elem_user_info; + if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) + kctl.info = snd_ctl_elem_user_enum_info; + else + kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) @@ -1122,6 +1181,11 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (info->count > 64) return -EINVAL; break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + private_size = sizeof(unsigned int); + if (info->count > 128 || info->value.enumerated.items == 0) + return -EINVAL; + break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); if (info->count > 512) @@ -1143,9 +1207,17 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, ue->info.access = 0; ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; + if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { + err = snd_ctl_elem_init_enum_names(ue); + if (err < 0) { + kfree(ue); + return err; + } + } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { + kfree(ue->priv_data); kfree(ue); return -ENOMEM; } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 426874429a5..2bb95a7a880 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -83,6 +83,8 @@ struct snd_ctl_elem_info32 { u32 items; u32 item; char name[64]; + u64 names_ptr; + u32 names_length; } enumerated; unsigned char reserved[128]; } value; @@ -372,6 +374,8 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, &data32->value.enumerated, sizeof(data->value.enumerated))) goto error; + data->value.enumerated.names_ptr = + (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); break; default: break; diff --git a/sound/core/jack.c b/sound/core/jack.c index 53b53e97c89..240a3e13470 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -30,6 +30,7 @@ static int jack_switch_types[] = { SW_LINEOUT_INSERT, SW_JACK_PHYSICAL_INSERT, SW_VIDEOOUT_INSERT, + SW_LINEIN_INSERT, }; static int snd_jack_dev_free(struct snd_device *device) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index d8359cfeca1..1b5e0c49a0a 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, name); + strlcpy(id.name, name, sizeof(id.name)); id.index = index; return snd_ctl_find_id(card, &id); } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 1c6be91dfb9..77d7df22e7c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2058,16 +2058,12 @@ EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, - int stream, - struct snd_pcm_file **rpcm_file) + int stream) { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; int err; - if (rpcm_file) - *rpcm_file = NULL; - err = snd_pcm_open_substream(pcm, stream, file, &substream); if (err < 0) return err; @@ -2083,8 +2079,7 @@ static int snd_pcm_open_file(struct file *file, substream->pcm_release = pcm_release_private; } file->private_data = pcm_file; - if (rpcm_file) - *rpcm_file = pcm_file; + return 0; } @@ -2113,7 +2108,6 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) { int err; - struct snd_pcm_file *pcm_file; wait_queue_t wait; if (pcm == NULL) { @@ -2131,7 +2125,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) add_wait_queue(&pcm->open_wait, &wait); mutex_lock(&pcm->open_mutex); while (1) { - err = snd_pcm_open_file(file, pcm, stream, &pcm_file); + err = snd_pcm_open_file(file, pcm, stream); if (err >= 0) break; if (err == -EAGAIN) { @@ -3156,8 +3150,8 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { /* * mmap the DMA buffer on RAM */ -static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *area) +int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *area) { area->vm_flags |= VM_RESERVED; #ifdef ARCH_HAS_DMA_MMAP_COHERENT @@ -3177,6 +3171,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; } +EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); /* * mmap the DMA buffer on I/O memory area @@ -3242,7 +3237,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, if (substream->ops->mmap) err = substream->ops->mmap(substream, area); else - err = snd_pcm_default_mmap(substream, area); + err = snd_pcm_lib_default_mmap(substream, area); if (!err) atomic_inc(&substream->mmap_count); return err; diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index a0da7755fce..4067f154894 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -575,7 +575,8 @@ static void loopback_runtime_free(struct snd_pcm_runtime *runtime) static int loopback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + return snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(params)); } static int loopback_hw_free(struct snd_pcm_substream *substream) @@ -587,7 +588,7 @@ static int loopback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dpcm->loopback->cable_lock); cable->valid &= ~(1 << substream->stream); mutex_unlock(&dpcm->loopback->cable_lock); - return snd_pcm_lib_free_pages(substream); + return snd_pcm_lib_free_vmalloc_buffer(substream); } static unsigned int get_cable_index(struct snd_pcm_substream *substream) @@ -740,6 +741,8 @@ static struct snd_pcm_ops loopback_playback_ops = { .prepare = loopback_prepare, .trigger = loopback_trigger, .pointer = loopback_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, }; static struct snd_pcm_ops loopback_capture_ops = { @@ -751,6 +754,8 @@ static struct snd_pcm_ops loopback_capture_ops = { .prepare = loopback_prepare, .trigger = loopback_trigger, .pointer = loopback_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, }; static int __devinit loopback_pcm_new(struct loopback *loopback, @@ -771,10 +776,6 @@ static int __devinit loopback_pcm_new(struct loopback *loopback, strcpy(pcm->name, "Loopback PCM"); loopback->pcm[device] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 2 * 1024 * 1024); return 0; } diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index 3fc257da180..cbe6bb9e53b 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c @@ -778,9 +778,10 @@ static int __devexit fwspk_remove(struct device *dev) { struct fwspk *fwspk = dev_get_drvdata(dev); - mutex_lock(&fwspk->mutex); amdtp_out_stream_pcm_abort(&fwspk->stream); snd_card_disconnect(fwspk->card); + + mutex_lock(&fwspk->mutex); fwspk_stop_stream(fwspk); mutex_unlock(&fwspk->mutex); @@ -796,8 +797,8 @@ static void fwspk_bus_reset(struct fw_unit *unit) fcp_bus_reset(fwspk->unit); if (cmp_connection_update(&fwspk->connection) < 0) { - mutex_lock(&fwspk->mutex); amdtp_out_stream_pcm_abort(&fwspk->stream); + mutex_lock(&fwspk->mutex); fwspk_stop_stream(fwspk); mutex_unlock(&fwspk->mutex); return; diff --git a/sound/oss/sound_timer.c b/sound/oss/sound_timer.c index 48cda6c4c25..8021c85f076 100644 --- a/sound/oss/sound_timer.c +++ b/sound/oss/sound_timer.c @@ -320,7 +320,7 @@ void sound_timer_init(struct sound_lowlev_timer *t, char *name) n = sound_alloc_timerdev(); if (n == -1) n = 0; /* Overwrite the system timer */ - strcpy(sound_timer.info.name, name); + strlcpy(sound_timer.info.name, name, sizeof(sound_timer.info.name)); sound_timer_devs[n] = &sound_timer; } EXPORT_SYMBOL(sound_timer_init); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c55b1b319b7..136f7232bb7 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -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) @@ -728,11 +729,14 @@ static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" }, }; +#define get_tea575x_gpio(chip) \ + (&snd_fm801_tea575x_gpios[((chip)->tea575x_tuner & TUNER_TYPE_MASK) - 1]) + static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) { struct fm801 *chip = tea->private_data; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; + struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); reg &= ~(FM801_GPIO_GP(gpio.data) | FM801_GPIO_GP(gpio.clk) | @@ -750,7 +754,7 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) { struct fm801 *chip = tea->private_data; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; + struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 | (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0; @@ -760,7 +764,7 @@ static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output { struct fm801 *chip = tea->private_data; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1]; + struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); /* use GPIO lines and set write enable bit */ reg |= FM801_GPIO_GS(gpio.data) | @@ -1150,7 +1154,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 +1241,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) { @@ -1245,17 +1249,19 @@ static int __devinit snd_fm801_create(struct snd_card *card, chip->tea575x_tuner = tea575x_tuner; if (!snd_tea575x_init(&chip->tea)) { snd_printk(KERN_INFO "detected TEA575x radio type %s\n", - snd_fm801_tea575x_gpios[tea575x_tuner - 1].name); + get_tea575x_gpio(chip)->name); break; } } 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, get_tea575x_gpio(chip)->name, + sizeof(chip->tea.card)); + } #endif *rchip = chip; diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 87365d5ea2a..f928d663472 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -6,6 +6,9 @@ snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o +# for trace-points +CFLAGS_hda_codec.o := -I$(src) + snd-hda-codec-realtek-objs := patch_realtek.o snd-hda-codec-cmedia-objs := patch_cmedia.o snd-hda-codec-analog-objs := patch_analog.o diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 21ec2cb100b..3b5170b9700 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -7,9 +7,6 @@ enum { ALC260_AUTO, ALC260_BASIC, - ALC260_HP, - ALC260_HP_DC7600, - ALC260_HP_3013, ALC260_FUJITSU_S702X, ALC260_ACER, ALC260_WILL, @@ -142,8 +139,6 @@ static const struct hda_channel_mode alc260_modes[1] = { /* Mixer combinations * * basic: base_output + input + pc_beep + capture - * HP: base_output + input + capture_alt - * HP_3013: hp_3013 + input + capture * fujitsu: fujitsu + capture * acer: acer + capture */ @@ -170,145 +165,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = { { } /* end */ }; -/* update HP, line and mono out pins according to the master switch */ -static void alc260_hp_master_update(struct hda_codec *codec) -{ - update_speakers(codec); -} - -static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - *ucontrol->value.integer.value = !spec->master_mute; - return 0; -} - -static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - int val = !*ucontrol->value.integer.value; - - if (val == spec->master_mute) - return 0; - spec->master_mute = val; - alc260_hp_master_update(codec); - return 1; -} - -static const struct snd_kcontrol_new alc260_hp_output_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, - .info = snd_ctl_boolean_mono_info, - .get = alc260_hp_master_sw_get, - .put = alc260_hp_master_sw_put, - }, - HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, - HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT), - { } /* end */ -}; - -static const struct hda_verb alc260_hp_unsol_verbs[] = { - {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {}, -}; - -static void alc260_hp_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x0f; - spec->autocfg.speaker_pins[0] = 0x10; - spec->autocfg.speaker_pins[1] = 0x11; - spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_PIN; -} - -static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, - .info = snd_ctl_boolean_mono_info, - .get = alc260_hp_master_sw_get, - .put = alc260_hp_master_sw_put, - }, - HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static void alc260_hp_3013_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x10; - spec->autocfg.speaker_pins[1] = 0x11; - spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_PIN; -} - -static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -static const struct hda_bind_ctls alc260_dc7600_bind_switch = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = { - HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol), - HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct hda_verb alc260_hp_3013_unsol_verbs[] = { - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {}, -}; - -static void alc260_hp_3012_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x10; - spec->autocfg.speaker_pins[0] = 0x0f; - spec->autocfg.speaker_pins[1] = 0x11; - spec- |