diff options
Diffstat (limited to 'sound')
28 files changed, 529 insertions, 272 deletions
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index f0ebc971c68..1dd66ddffca 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -897,6 +897,15 @@ static int tas_create(struct i2c_adapter *adapter, client = i2c_new_device(adapter, &info); if (!client) return -ENODEV; + /* + * We know the driver is already loaded, so the device should be + * already bound. If not it means binding failed, and then there + * is no point in keeping the device instantiated. + */ + if (!client->driver) { + i2c_unregister_device(client); + return -ENODEV; + } /* * Let i2c-core delete that device on driver removal. diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 4e34d19ddbc..b4b48afb6de 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -137,9 +137,9 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card) return 0; } -static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state) +static int pxa2xx_ac97_suspend(struct device *dev) { - struct snd_card *card = platform_get_drvdata(dev); + struct snd_card *card = dev_get_drvdata(dev); int ret = 0; if (card) @@ -148,9 +148,9 @@ static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state) return ret; } -static int pxa2xx_ac97_resume(struct platform_device *dev) +static int pxa2xx_ac97_resume(struct device *dev) { - struct snd_card *card = platform_get_drvdata(dev); + struct snd_card *card = dev_get_drvdata(dev); int ret = 0; if (card) @@ -159,9 +159,10 @@ static int pxa2xx_ac97_resume(struct platform_device *dev) return ret; } -#else -#define pxa2xx_ac97_suspend NULL -#define pxa2xx_ac97_resume NULL +static struct dev_pm_ops pxa2xx_ac97_pm_ops = { + .suspend = pxa2xx_ac97_suspend, + .resume = pxa2xx_ac97_resume, +}; #endif static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) @@ -241,11 +242,12 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) static struct platform_driver pxa2xx_ac97_driver = { .probe = pxa2xx_ac97_probe, .remove = __devexit_p(pxa2xx_ac97_remove), - .suspend = pxa2xx_ac97_suspend, - .resume = pxa2xx_ac97_resume, .driver = { .name = "pxa2xx-ac97", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &pxa2xx_ac97_pm_ops, +#endif }, }; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 561d6d95a2d..ab73edf2c89 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2985,7 +2985,7 @@ static int snd_pcm_mmap_status_fault(struct vm_area_struct *area, return 0; } -static struct vm_operations_struct snd_pcm_vm_ops_status = +static const struct vm_operations_struct snd_pcm_vm_ops_status = { .fault = snd_pcm_mmap_status_fault, }; @@ -3024,7 +3024,7 @@ static int snd_pcm_mmap_control_fault(struct vm_area_struct *area, return 0; } -static struct vm_operations_struct snd_pcm_vm_ops_control = +static const struct vm_operations_struct snd_pcm_vm_ops_control = { .fault = snd_pcm_mmap_control_fault, }; @@ -3094,7 +3094,7 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, return 0; } -static struct vm_operations_struct snd_pcm_vm_ops_data = +static const struct vm_operations_struct snd_pcm_vm_ops_data = { .open = snd_pcm_mmap_data_open, .close = snd_pcm_mmap_data_close, @@ -3118,7 +3118,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, * mmap the DMA buffer on I/O memory area */ #if SNDRV_PCM_INFO_MMAP_IOMEM -static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = +static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio = { .open = snd_pcm_mmap_data_open, .close = snd_pcm_mmap_data_close, diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index c52691c2fc4..9a88cdfd952 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -915,7 +915,7 @@ static int __devinit hal2_probe(struct platform_device *pdev) return 0; } -static int __exit hal2_remove(struct platform_device *pdev) +static int __devexit hal2_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index e497525bc11..8691f4cf619 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -973,7 +973,7 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) return 0; } -static int __exit snd_sgio2audio_remove(struct platform_device *pdev) +static int __devexit snd_sgio2audio_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index b1b3a644f73..75454648d50 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1037,7 +1037,7 @@ static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state) static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state) { - return atc_daio_unmute(atc, state, LINEO4); + return atc_daio_unmute(atc, state, LINEO2); } static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state) @@ -1047,7 +1047,7 @@ static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state) static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state) { - return atc_daio_unmute(atc, state, LINEO2); + return atc_daio_unmute(atc, state, LINEO4); } static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state) diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index da2065cd2c0..1305f7ca02c 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -950,7 +950,7 @@ static int __devinit snd_echo_new_pcm(struct echoaudio *chip) Control interface ******************************************************************************/ -#ifndef ECHOCARD_HAS_VMIXER +#if !defined(ECHOCARD_HAS_VMIXER) || defined(ECHOCARD_HAS_LINE_OUT_GAIN) /******************* PCM output volume *******************/ static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, @@ -1003,6 +1003,19 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, return changed; } +#ifdef ECHOCARD_HAS_LINE_OUT_GAIN +/* On the Mia this one controls the line-out volume */ +static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { + .name = "Line Playback Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .info = snd_echo_output_gain_info, + .get = snd_echo_output_gain_get, + .put = snd_echo_output_gain_put, + .tlv = {.p = db_scale_output_gain}, +}; +#else static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { .name = "PCM Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1012,9 +1025,10 @@ static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { .put = snd_echo_output_gain_put, .tlv = {.p = db_scale_output_gain}, }; - #endif +#endif /* !ECHOCARD_HAS_VMIXER || ECHOCARD_HAS_LINE_OUT_GAIN */ + #ifdef ECHOCARD_HAS_INPUT_GAIN @@ -2030,10 +2044,18 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) goto ctl_error; -#else - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_pcm_output_gain, chip))) < 0) +#ifdef ECHOCARD_HAS_LINE_OUT_GAIN + err = snd_ctl_add(chip->card, + snd_ctl_new1(&snd_echo_line_output_gain, chip)); + if (err < 0) goto ctl_error; #endif +#else /* ECHOCARD_HAS_VMIXER */ + err = snd_ctl_add(chip->card, + snd_ctl_new1(&snd_echo_pcm_output_gain, chip)); + if (err < 0) + goto ctl_error; +#endif /* ECHOCARD_HAS_VMIXER */ #ifdef ECHOCARD_HAS_INPUT_GAIN if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0) diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index f3b9b45c9c1..f05c8c097aa 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -29,6 +29,7 @@ #define ECHOCARD_HAS_ADAT FALSE #define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 #define ECHOCARD_HAS_MIDI +#define ECHOCARD_HAS_LINE_OUT_GAIN /* Pipe indexes */ #define PX_ANALOG_OUT 0 /* 8 */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 20a66f85f0a..c9ad182e1b4 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2303,6 +2303,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) * white-list for enable_msi */ static struct snd_pci_quirk msi_white_list[] __devinitdata = { + SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1), SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1), {} }; diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 215e72a8711..2d603f6aba6 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -4032,6 +4032,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec) } /* + * HP Touchsmart + * port-A (0x11) - front hp-out + * port-B (0x14) - unused + * port-C (0x15) - unused + * port-D (0x12) - rear line out + * port-E (0x1c) - front mic-in + * port-F (0x16) - Internal speakers + * digital-mic (0x17) - Internal mic + */ + +static struct hda_verb ad1984a_touchsmart_verbs[] = { + /* DACs; unmute as default */ + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + /* Port-A (HP) mixer - route only from analog mixer */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-A pin */ + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + /* Port-A (HP) pin - always unmuted */ + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Port-E (int speaker) mixer - route only from analog mixer */ + {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, + /* Port-E pin */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + /* Port-F (int speaker) mixer - route only from analog mixer */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-F pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog mixer; mute as default */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* capture sources */ + /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* unsolicited event for pin-sense */ + {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, + {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, + /* allow to touch GPIO1 (for mute control) */ + {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ + /* internal mic - dmic */ + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* set magic COEFs for dmic */ + {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, + {0x01, AC_VERB_SET_PROC_COEF, 0x08}, + { } /* end */ +}; + +static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), +/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .info = snd_hda_mixer_amp_switch_info, + .get = snd_hda_mixer_amp_switch_get, + .put = ad1884a_mobile_master_sw_put, + .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), + }, + HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), + { } /* end */ +}; + +/* switch to external mic if plugged */ +static void ad1984a_touchsmart_automic(struct hda_codec *codec) +{ + if (snd_hda_codec_read(codec, 0x1c, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { + snd_hda_codec_write(codec, 0x0c, 0, + AC_VERB_SET_CONNECT_SEL, 0x4); + } else { + snd_hda_codec_write(codec, 0x0c, 0, + AC_VERB_SET_CONNECT_SEL, 0x5); + } +} + + +/* unsolicited event for HP jack sensing */ +static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case AD1884A_HP_EVENT: + ad1884a_hp_automute(codec); + break; + case AD1884A_MIC_EVENT: + ad1984a_touchsmart_automic(codec); + break; + } +} + +/* initialize jack-sensing, too */ +static int ad1984a_touchsmart_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1884a_hp_automute(codec); + ad1984a_touchsmart_automic(codec); + return 0; +} + + +/* */ enum { @@ -4039,6 +4160,7 @@ enum { AD1884A_LAPTOP, AD1884A_MOBILE, AD1884A_THINKPAD, + AD1984A_TOUCHSMART, AD1884A_MODELS }; @@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = { [AD1884A_LAPTOP] = "laptop", [AD1884A_MOBILE] = "mobile", [AD1884A_THINKPAD] = "thinkpad", + [AD1984A_TOUCHSMART] = "touchsmart", }; static struct snd_pci_quirk ad1884a_cfg_tbl[] = { @@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), + SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), {} }; @@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; codec->patch_ops.init = ad1984a_thinkpad_init; break; + case AD1984A_TOUCHSMART: + spec->mixers[0] = ad1984a_touchsmart_mixers; + spec->init_verbs[0] = ad1984a_touchsmart_verbs; + spec->multiout.dig_out_nid = 0; + codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; + codec->patch_ops.init = ad1984a_touchsmart_init; + /* set the upper-limit for mixer amp to 0dB for avoiding the + * possible damage by overloading + */ + snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); + break; } return 0; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 9d899eda44d..3fbbc8c01e7 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -682,11 +682,13 @@ static struct hda_input_mux cxt5045_capture_source = { }; static struct hda_input_mux cxt5045_capture_source_benq = { - .num_items = 3, + .num_items = 5, .items = { { "IntMic", 0x1 }, { "ExtMic", 0x2 }, { "LineIn", 0x3 }, + { "CD", 0x4 }, + { "Mixer", 0x0 }, } }; @@ -811,11 +813,19 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { }; static struct snd_kcontrol_new cxt5045_benq_mixers[] = { + HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT), + HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT), + {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 12960581956..7810d3dcad8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = { .init_hook = alc268_toshiba_automute, }, [ALC268_ACER] = { - .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer, + .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, alc268_beep_mixer }, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_verbs }, @@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4), SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), @@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = { * BIOS auto configuration */ +/* convert from MIX nid to DAC */ +static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) +{ + if (nid == 0x0f) + return 0x02; + else if (nid >= 0x0c && nid <= 0x0e) + return nid - 0x0c + 0x02; + else + return 0; +} + +/* get MIX nid connected to the given pin targeted to DAC */ +static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, + hda_nid_t dac) +{ + hda_nid_t mix[4]; + int i, num; + + num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); + for (i = 0; i < num; i++) { + if (alc662_mix_to_dac(mix[i]) == dac) + return mix[i]; + } + return 0; +} + +/* look for an empty DAC slot */ +static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t srcs[5]; + int i, j, num; + + num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); + if (num < 0) + return 0; + for (i = 0; i < num; i++) { + hda_nid_t nid = alc662_mix_to_dac(srcs[i]); + if (!nid) + continue; + for (j = 0; j < spec->multiout.num_dacs; j++) + if (spec->multiout.dac_nids[j] == nid) + break; + if (j >= spec->multiout.num_dacs) + return nid; + } + return 0; +} + +/* fill in the dac_nids table from the parsed pin configuration */ +static int alc662_auto_fill_dac_nids(struct hda_codec *codec, + const struct auto_pin_cfg *cfg) +{ + struct alc_spec *spec = codec->spec; + int i; + hda_nid_t dac; + + spec->multiout.dac_nids = spec->private_dac_nids; + for (i = 0; i < cfg->line_outs; i++) { + dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]); + if (!dac) + continue; + spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; + } + return 0; +} + +static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, + hda_nid_t nid, unsigned int chs) +{ + char name[32]; + sprintf(name, "%s Playback Volume", pfx); + return add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); +} + +static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, + hda_nid_t nid, unsigned int chs) +{ + char name[32]; + sprintf(name, "%s Playback Switch", pfx); + return add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); +} + +#define alc662_add_stereo_vol(spec, pfx, nid) \ + alc662_add_vol_ctl(spec, pfx, nid, 3) +#define alc662_add_stereo_sw(spec, pfx, nid) \ + alc662_add_sw_ctl(spec, pfx, nid, 3) + /* add playback controls from the parsed DAC table */ -static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, +static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { - char name[32]; + struct alc_spec *spec = codec->spec; static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; - hda_nid_t nid; + hda_nid_t nid, mix; int i, err; for (i = 0; i < cfg->line_outs; i++) { - if (!spec->multiout.dac_nids[i]) + nid = spec->multiout.dac_nids[i]; + if (!nid) + continue; + mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); + if (!mix) continue; - nid = alc880_idx_to_dac(i); if (i == 2) { /* Center/LFE */ - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Center Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, - HDA_OUTPUT)); + err = alc662_add_vol_ctl(spec, "Center", nid, 1); if (err < 0) return err; - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "LFE Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, - HDA_OUTPUT)); + err = alc662_add_vol_ctl(spec, "LFE", nid, 2); if (err < 0) return err; - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(0x0e, 1, 0, - HDA_INPUT)); + err = alc662_add_sw_ctl(spec, "Center", mix, 1); if (err < 0) return err; - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, - HDA_INPUT)); + err = alc662_add_sw_ctl(spec, "LFE", mix, 2); if (err < 0) return err; } else { const char *pfx; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { - if (!cfg->hp_pins) + if (cfg->hp_outs) pfx = "Speaker"; else pfx = "PCM"; } else pfx = chname[i]; - sprintf(name, "%s Playback Volume", pfx); - err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, - HDA_OUTPUT)); + err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) pfx = "Speaker"; - sprintf(name, "%s Playback Switch", pfx); - err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i), - 3, 0, HDA_INPUT)); + err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err; } @@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, } /* add playback controls for speaker and HP outputs */ -static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, +/* return DAC nid if any new DAC is assigned */ +static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, const char *pfx) { - hda_nid_t nid; + struct alc_spec *spec = codec->spec; + hda_nid_t nid, mix; int err; - char name[32]; if (!pin) return 0; - - if (pin == 0x17) { - /* ALC663 has a mono output pin on 0x17 */ + nid = alc662_look_for_dac(codec, pin); + if (!nid) { + char name[32]; + /* the corresponding DAC is already occupied */ + if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) + return 0; /* no way */ + /* create a switch only */ sprintf(name, "%s Playback Switch", pfx); - err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); - return err; + return add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); } - if (alc880_is_fixed_pin(pin)) { - nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); - /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ - /* specify the DAC as the extra output */ - if (!spec->multiout.hp_nid) - spec->multiout.hp_nid = nid; - else - spec->multiout.extra_out_nid[0] = nid; - /* control HP volume/switch on the output mixer amp */ - nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); - sprintf(name, "%s Playback Volume", pfx); - err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - sprintf(name, "%s Playback Switch", pfx); - err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); - if (err < 0) - return err; - } else if (alc880_is_multi_pin(pin)) { - /* set manual connection */ - /* we have only a switch on HP-out PIN */ - sprintf(name, "%s Playback Switch", pfx); - err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - } - return 0; + mix = alc662_dac_to_mix(codec, pin, nid); + if (!mix) + return 0; + err = alc662_add_vol_ctl(spec, pfx, nid, 3); + if (err < 0) + return err; + err = alc662_add_sw_ctl(spec, pfx, mix, 3); + if (err < 0) + return err; + return nid; } /* create playback/capture controls for input pins */ @@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, - int dac_idx) + hda_nid_t dac) { + int i, num; + hda_nid_t srcs[4]; + alc_set_pin_output(codec, nid, pin_type); /* need the manual connection? */ - if (alc880_is_multi_pin(nid)) { - struct alc_spec *spec = codec->spec; - int idx = alc880_multi_pin_idx(nid); - snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, - AC_VERB_SET_CONNECT_SEL, - alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); + num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); + if (num <= 1) + return; + for (i = 0; i < num; i++) { + if (alc662_mix_to_dac(srcs[i]) != dac) + continue; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); + return; } } static void alc662_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + int pin_type = get_pin_type(spec->autocfg.line_out_type); int i; for (i = 0; i <= HDA_SIDE; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; - int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) alc662_auto_set_output_and_unmute(codec, nid, pin_type, - i); + spec->multiout.dac_nids[i]); } } @@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) hda_nid_t pin; pin = spec->autocfg.hp_pins[0]; - if (pin) /* connect to front */ - /* use dac 0 */ - alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); + if (pin) + alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, + spec->multiout.hp_nid); pin = spec->autocfg.speaker_pins[0]; if (pin) - alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); + alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, + spec->multiout.extra_out_nid[0]); } #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID @@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec) if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ - err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); + err = alc662_auto_fill_dac_nids(codec, &spec->autocfg); if (err < 0) return err; - err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); + err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg); if (err < 0) return err; - err = alc662_auto_create_extra_out(spec, + err = alc662_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0], "Speaker"); if (err < 0) return err; - err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], + if (err) + spec->multiout.extra_out_nid[0] = err; + err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], "Headphone"); if (err < 0) return err; + if (err) + spec->multiout.hp_nid = err; err = alc662_auto_create_input_ctls(codec, &spec->autocfg); if (err < 0) return err; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 826137ec300..a9b26828a65 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -182,8 +182,8 @@ struct sigmatel_jack { struct sigmatel_mic_route { hda_nid_t pin; - unsigned char mux_idx; - unsigned char dmux_idx; + signed char mux_idx; + signed char dmux_idx; }; struct sigmatel_spec { @@ -3469,18 +3469,26 @@ static int set_mic_route(struct hda_codec *codec, break; if (i <= AUTO_PIN_FRONT_MIC) { /* analog pin */ - mic->dmux_idx = 0; i = get_connection_index(codec, spec->mux_nids[0], pin); if (i < 0) return -1; mic->mux_idx = i; + mic->dmux_idx = -1; + if (spec->dmux_nids) + mic->dmux_idx = get_connection_index(codec, + spec->dmux_nids[0], + spec->mux_nids[0]); } else if (spec->dmux_nids) { /* digital pin */ - mic->mux_idx = 0; i = get_connection_index(codec, spec->dmux_nids[0], pin); if (i < 0) return -1; mic->dmux_idx = i; + mic->mux_idx = -1; + if (spec->mux_nids) + mic->mux_idx = get_connection_index(codec, + spec->mux_nids[0], + spec->dmux_nids[0]); } return 0; } @@ -4557,11 +4565,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec) mic = &spec->ext_mic; else mic = &spec->int_mic; - if (mic->dmux_idx) + if (mic->dmux_idx >= 0) snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, AC_VERB_SET_CONNECT_SEL, mic->dmux_idx); - else + if (mic->mux_idx >= 0) snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, AC_VERB_SET_CONNECT_SEL, mic->mux_idx); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 171ada53520..754867ed478 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1954,6 +1954,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Sony S1XP", .type = AC97_TUNE_INV_EAPD }, + { + .subvendor = 0x104d, + .subdevice = 0x81c0, + .name = "Sony VAIO VGN-T350P", /*AD1981B*/ + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x104d, + .subdevice = 0x81c5, + .name = "Sony VAIO VGN-B1VP", /*AD1981B*/ + .type = AC97_TUNE_INV_EAPD + }, { .subvendor = 0x1043, .subdevice = 0x80f3, diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 835fa19ed46..d06f780bd7e 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -59,6 +59,18 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) strlcpy(info.type, "keywest", I2C_NAME_SIZE); info.addr = keywest_ctx->addr; keywest_ctx->client = i2c_new_device(adapter, &info); + if (!keywest_ctx->client) + return -ENODEV; + /* + * We know the driver is already loaded, so the device should be + * already bound. If not it means binding failed, and then there + * is no point in keeping the device instantiated. + */ + if (!keywest_ctx->client->driver) { + i2c_unregister_device(keywest_ctx->client); + keywest_ctx->client = NULL; + return -ENODEV; + } /* * Let i2c-core delete that device on driver removal. @@ -86,7 +98,7 @@ static const struct i2c_device_id keywest_i2c_id[] = { { } }; -struct i2c_driver keywest_driver = { +static struct i2c_driver keywest_driver = { .driver = { .name = "PMac Keywest Audio", }, diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index ac927ffdc96..97f1a251e44 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -7,15 +7,6 @@ config SND_BF5XX_I2S mode (supports single stereo In/Out). You will also need to select the audio interfaces to support below. -config SND_BF5XX_TDM - tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" - depends on (BLACKFIN && SND_SOC) - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in TDM - mode. - You will also need to select the audio interfaces to support below. - config SND_BF5XX_SOC_SSM2602 tristate "SoC SSM2602 Audio support for BF52x ezkit" depends on SND_BF5XX_I2S @@ -41,6 +32,31 @@ config SND_BFIN_AD73311_SE Enter the GPIO used to control AD73311's SE pin. Acceptable values are 0 to 7 +config SND_BF5XX_TDM + tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" + depends on (BLACKFIN && SND_SOC) + help + Say Y or M if you want to add support for codecs attached to + the Blackfin SPORT (synchronous serial ports) interface in TDM + mode. + You will also need to select the audio interfaces to support below. + +config SND_BF5XX_SOC_AD1836 + tristate "SoC AD1836 Audio support for BF5xx" + depends on SND_BF5XX_TDM + select SND_BF5XX_SOC_TDM + select SND_SOC_AD1836 + help + Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. + +config SND_BF5XX_SOC_AD1938 + tristate "SoC AD1938 Audio support for Blackfin" + depends on SND_BF5XX_TDM + select SND_BF5XX_SOC_TDM + select SND_SOC_AD1938 + help + Say Y if you want to add support for AD1938 codec on Blackfin. + config SND_BF5XX_AC97 tristate "SoC AC97 Audio for the ADI BF5xx chip" depends on BLACKFIN @@ -71,6 +87,30 @@ config SND_BF5XX_MULTICHAN_SUPPORT Say y if you want AC97 driver to support up to 5.1 channel audio. this mode will consume much more memory for DMA. +config SND_BF5XX_HAVE_COLD_RESET + bool "BOARD has COLD Reset GPIO" + depends on SND_BF5XX_AC97 + default y if BFIN548_EZKIT + default n if !BFIN548_EZKIT + +config SND_BF5XX_RESET_GPIO_NUM + int "Set a GPIO for cold reset" + depends on SND_BF5XX_HAVE_COLD_RESET + range 0 159 + default 19 if BFIN548_EZKIT + default 5 if BFIN537_STAMP + default 0 + help + Set the correct GPIO for RESET the sound chip. + +config SND_BF5XX_SOC_AD1980 + tristate "SoC AD1980/1 Audio support for BF5xx" + depends on SND_BF5XX_AC97 + select SND_BF5XX_SOC_AC97 + select SND_SOC_AD1980 + help + Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. + config SND_BF5XX_SOC_SPORT tristate @@ -88,30 +128,6 @@ config SND_BF5XX_SOC_AC97 select SND_SOC_AC97_BUS select SND_BF5XX_SOC_SPORT -config SND_BF5XX_SOC_AD1836 - tristate "SoC AD1836 Audio support for BF5xx" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1836 - help - Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. - -config SND_BF5XX_SOC_AD1980 - tristate "SoC AD1980/1 Audio support for BF5xx" - depends on SND_BF5XX_AC97 - select SND_BF5XX_SOC_AC97 - select SND_SOC_AD1980 - help - Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. - -config SND_BF5XX_SOC_AD1938 - tristate "SoC AD1938 Audio support for Blackfin" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1938 - help - Say Y if you want to add support for AD1938 codec on Blackfin. - config SND_BF5XX_SPORT_NUM int "Set a SPORT for Sound chip" depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) @@ -120,19 +136,3 @@ config SND_BF5XX_SPORT_NUM default 0 help Set the correct SPORT for sound chip. - -config SND_BF5XX_HAVE_COLD_RESET - bool "BOARD has COLD Reset GPIO" - depends on SND_BF5XX_AC97 - default y if BFIN548_EZKIT - default n if !BFIN548_EZKIT - -config SND_BF5XX_RESET_GPIO_NUM - int "Set a GPIO for cold reset" - depends on SND_BF5XX_HAVE_COLD_RESET - range 0 159 - default 19 if BFIN548_EZKIT - default 5 if BFIN537_STAMP - default 0 - help - Set the correct GPIO for RESET the sound chip. diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 1e9d161c76c..084b68884ad 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -77,12 +77,12 @@ static struct sport_param sport_params[2] = { * TFS. When Port G is selected and EMAC then there is a conflict between * the PHY interrupt line and TFS. Current settings prevent the conflict * by ignoring the TFS pin when Port G is selected. This allows both - * ssm2602 using Port G and EMAC concurrently. + * codecs and EMAC using Port G concurrently. */ -#ifdef CONFIG_BF527_SPORT0_PORTF -#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) -#else +#ifdef CONFIG_BF527_SPORT0_PORTG #define LOCAL_SPORT0_TFS (0) +#else +#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) #endif static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 3096badf09a..ff546e91a22 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c @@ -78,12 +78,12 @@ static struct sport_param sport_params[2] = { * TFS. When Port G is selected and EMAC then there is a conflict between * the PHY interrupt line and TFS. Current settings prevent the conflict * by ignoring the TFS pin when Port G is selected. This allows both - * ssm2602 using Port G and EMAC concurrently. + * codecs and EMAC using Port G concurrently. */ -#ifdef CONFIG_BF527_SPORT0_PORTF -#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) -#else +#ifdef CONFIG_BF527_SPORT0_PORTG #define LOCAL_SPORT0_TFS (0) +#else +#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) #endif static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 12a6c549ee6..4ae70704802 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -97,22 +97,19 @@ enum { DAVINCI_MCBSP_WORD_32, }; -static struct davinci_pcm_dma_params davinci_i2s_pcm_out = { - .name = "I2S PCM Stereo out", -}; - -static struct davinci_pcm_dma_params davinci_i2s_pcm_in = { - .name = "I2S PCM Stereo in", -}; - struct davinci_mcbsp_dev { + /* + * dma_params must be first because rtd->dai->cpu_dai->private_data + * is cast to a pointer of an array of struct davinci_pcm_dma_params in + * davinci_pcm_open. + */ + struct davinci_pcm_dma_params dma_params[2]; void __iomem *base; #define MOD_DSP_A 0 #define MOD_DSP_B 1 int mode; u32 pcr; struct clk *clk; - struct davinci_pcm_dma_params *dma_params[2]; }; static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, @@ -215,14 +212,6 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) toggle_clock(dev, playback); } -static int davinci_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_mcbsp_dev *dev = cpu_dai->private_data; - cpu_dai->dma_data = dev->dma_params[substream->stream]; - return 0; -} - #define DEFAULT_BITPERSAMPLE 16 static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, @@ -353,8 +342,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct davinci_pcm_dma_params *dma_params = dai->dma_data; struct davinci_mcbsp_dev *dev = dai->private_data; + struct davinci_pcm_dma_params *dma_params = + &dev->dma_params[substream->stream]; struct snd_interval *i = NULL; int mcbsp_word_length; unsigned int rcr, xcr, srgr; @@ -472,7 +462,6 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 static struct snd_soc_dai_ops davinci_i2s_dai_ops = { - .startup = davinci_i2s_startup, .shutdown = davinci_i2s_shutdown, .prepare = davinci_i2s_prepare, .trigger = davinci_i2s_trigger, @@ -534,12 +523,10 @@ static int davinci_i2s_probe(struct platform_device *pdev) dev->base = (void __iomem *)IO_ADDRESS(mem->start); - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out; - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr = + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in; - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr = + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); /* first TX, then RX */ @@ -549,7 +536,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) ret = -ENXIO; goto err_free_mem; } - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start; + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start; res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (!res) { @@ -557,7 +544,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) ret = -ENXIO; goto err_free_mem; } - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start; + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; davinci_i2s_dai.private_data = dev; ret = snd_soc_register_dai(&davinci_i2s_dai); diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 7a06c0a8666..5d1f98a4c97 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -332,14 +332,6 @@ static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val) printk(KERN_ERR "GBLCTL write error\n"); } -static int davinci_mcasp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = cpu_dai->private_data; - cpu_dai->dma_data = dev->dma_params[substream->stream]; - return 0; -} - static void mcasp_start_rx(struct davinci_audio_dev *dev) { mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); @@ -386,17 +378,17 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (dev->txnumevt) /* enable FIFO */ + mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + FIFO_ENABLE); mcasp_start_tx(dev); - else + } else { + if (dev->rxnumevt) /* enable FIFO */ + mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + FIFO_ENABLE); mcasp_start_rx(dev); - - /* enable FIFO */ - if (dev->txnumevt) - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - - if (dev->rxnumevt) - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } } static void mcasp_stop_rx(struct davinci_audio_dev *dev) @@ -413,17 +405,17 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (dev->txnumevt) /* disable FIFO */ + mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + FIFO_ENABLE); mcasp_stop_tx(dev); - else + } else { + if (dev->rxnumevt) /* disable FIFO */ + mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + FIFO_ENABLE); mcasp_stop_rx(dev); - - /* disable FIFO */ - if (dev->txnumevt) - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - - if (dev->rxnumevt) - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } } static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, @@ -720,7 +712,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, { struct davinci_audio_dev *dev = cpu_dai->private_data; struct davinci_pcm_dma_params *dma_params = - dev->dma_params[substream->stream]; + &dev->dma_params[substream->stream]; int word_length; u8 numevt; @@ -798,7 +790,6 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, } static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, .trigger = davinci_mcasp_trigger, .hw_params = davinci_mcasp_hw_params, .set_fmt = davinci_mcasp_set_dai_fmt, @@ -849,20 +840,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) struct resource *mem, *ioarea, *res; struct snd_platform_data *pdata; struct davinci_audio_dev *dev; - int count = 0; int ret = 0; dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL); if (!dev) return -ENOMEM; - dma_data = kzalloc(sizeof(struct davinci_pcm_dma_params) * 2, - GFP_KERNEL); - if (!dma_data) { - ret = -ENOMEM; - goto err_release_dev; - } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?\n"); @@ -897,11 +880,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dev->txnumevt = pdata->txnumevt; dev->rxnumevt = pdata->rxnumevt; - dma_data[count].name = "I2S PCM Stereo out"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t) (pdata->tx_dma_offset + + dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data->eventq_no = pdata->eventq_no; + dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &dma_data[count]; /* first TX, then RX */ res = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -910,13 +892,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) goto err_release_region; } - dma_data[count].channel = res->start; - count++; - dma_data[count].name = "I2S PCM Stereo in"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t)(pdata->rx_dma_offset + + dma_data->channel = res->start; + + dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_data->eventq_no = pdata->eventq_no; + dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &dma_data[count]; res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (!res) { @@ -924,7 +905,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) goto err_release_region; } - dma_data[count].channel = res->start; + dma_data->channel = res->start; davinci_mcasp_dai[pdata->op_mode].private_data = dev; davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); @@ -936,8 +917,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) err_release_region: release_mem_region(mem->start, (mem->end - mem->start) + 1); err_release_data: - kfree(dma_data); -err_release_dev: kfree(dev); return ret; @@ -946,7 +925,6 @@ err_release_dev: static int davinci_mcasp_remove(struct platform_device *pdev) { struct snd_platform_data *pdata = pdev->dev.platform_data; - struct davinci_pcm_dma_params *dma_data; struct davinci_audio_dev *dev; struct resource *mem; @@ -959,8 +937,6 @@ static int davinci_mcasp_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, (mem->end - mem->start) + 1); - dma_data = dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - kfree(dma_data); kfree(dev); return 0; diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 554354c1cc2..9d179cc88f7 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -39,10 +39,15 @@ enum { }; struct davinci_audio_dev { + /* + * dma_params must be first because rtd->dai->cpu_dai->private_data + * is cast to a pointer of an array of struct davinci_pcm_dma_params in + * davinci_pcm_open. + */ + struct davinci_pcm_dma_params dma_params[2]; void __iomem *base; int sample_rate; struct clk *clk; - struct davinci_pcm_dma_params *dma_params[2]; unsigned int codec_fmt; /* McASP specific data */ diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 2f7da49ed34..c73a915f233 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -126,16 +126,9 @@ static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data) static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) { struct davinci_runtime_data *prtd = substream->runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data; struct edmacc_param p_ram; int ret; - if (!dma_data) - return -ENODEV; - - prtd->params = dma_data; - /* Request master DMA channel */ ret = edma_alloc_channel(prtd->params->channel, davinci_pcm_dma_irq, substream, @@ -244,6 +237,11 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct davinci_runtime_data *prtd; int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->private_data; + struct davinci_pcm_dma_params *params = &pa[substream->stream]; + if (!params) + return -ENODEV; snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); /* ensure that buffer size is a multiple of period size */ @@ -257,6 +255,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) return -ENOMEM; spin_lock_init(&prtd->lock); + prtd->params = params; runtime->private_data = prtd; diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index 63d96253c73..8746606efc8 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -17,7 +17,6 @@ struct davinci_pcm_dma_params { - char *name; /* stream identifier */ int channel; /* sync dma channel ID */ unsigned short acnt; dma_addr_t dma_addr; /* device physical address for DMA */ diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 6375b4ea525..dcb3181bb34 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -138,7 +138,7 @@ config SND_PXA2XX_SOC_MIOA701 config SND_PXA2XX_SOC_IMOTE2 tristate "SoC Audio support for IMote 2" - depends on SND_PXA2XX_SOC && MACH_INTELMOTE2 + depends on SND_PXA2XX_SOC && MACH_INTELMOTE2 && I2C select SND_PXA2XX_SOC_I2S select SND_SOC_WM8940 help diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ab5a3ac2ac4..9efcfd08d74 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -898,6 +898,11 @@ static struct snd_kcontrol_new usb_feature_unit_ctl = { * build a feature control */ +static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) +{ + return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); +} + static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, unsigned int ctl_mask, int control, struct usb_audio_term *iterm, int unitid) @@ -978,13 +983,13 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, */ if (! mapped_name && ! (state->oterm.type >> 16)) { if ((state->oterm.type & 0xff00) == 0x0100) { - len = strlcat(kctl->id.name, " Capture", sizeof(kctl->id.name)); + len = append_ctl_name(kctl, " Capture"); } else { - len = strlcat(kctl->id.name + len, " Playback", sizeof(kctl->id.name)); + len = append_ctl_name(kctl, " Playback"); } } - strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", - sizeof(kctl->id.name)); + append_ctl_name(kctl, control == USB_FEATURE_MUTE ? + " Switch" : " Volume"); if (control == USB_FEATURE_VOLUME) { kctl->tlv.c = mixer_vol_tlv; kctl->vd[0].access |= @@ -1143,7 +1148,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc, len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); if (! len) len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); - strlcat(kctl->id.name + len, " Volume", sizeof(kctl->id.name)); + append_ctl_name(kctl, " Volume"); snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); @@ -1400,8 +1405,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned if (! len) strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); } - strlcat(kctl->id.name, " ", sizeof(kctl->id.name)); - strlcat(kctl->id.name, valinfo->suffix, sizeof(kctl->id.name)); + append_ctl_name(kctl, " "); + append_ctl_name(kctl, valinfo->suffix); snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); @@ -1610,9 +1615,9 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); if ((state->oterm.type & 0xff00) == 0x0100) - strlcat(kctl->id.name, " Capture Source", sizeof(kctl->id.name)); + append_ctl_name(kctl, " Capture Source"); else - strlcat(kctl->id.name, " Playback Source", sizeof(kctl->id.name)); + append_ctl_name(kctl, " Playback Source"); } snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index fd44946ce4b..99f33766cd5 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -154,7 +154,7 @@ static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } -static struct vm_operations_struct usb_stream_hwdep_vm_ops = { +static const struct vm_operations_struct usb_stream_hwdep_vm_ops = { .open = usb_stream_hwdep_vm_open, .fault = usb_stream_hwdep_vm_fault, .close = usb_stream_hwdep_vm_close, diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index f3d8f71265d..52e04b2f35d 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -53,7 +53,7 @@ static int snd_us428ctls_vm_fault(struct vm_area_struct *area, return 0; } -static struct vm_operations_struct us428ctls_vm_ops = { +static const struct vm_operations_struct us428ctls_vm_ops = { .fault = snd_us428ctls_vm_fault, }; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 117946f2deb..4b2304c2e02 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -697,7 +697,7 @@ static int snd_usX2Y_hwdep_pcm_vm_fault(struct vm_area_struct *area, } -static struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { +static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { .open = snd_usX2Y_hwdep_pcm_vm_open, .close = snd_usX2Y_hwdep_pcm_vm_close, .fault = snd_usX2Y_hwdep_pcm_vm_fault, |