]> Pileus Git - ~andy/linux/blobdiff - sound/pci/hda/hda_generic.c
Merge tag 'sunxi-fixes-for-3.14' of https://github.com/mripard/linux into fixes
[~andy/linux] / sound / pci / hda / hda_generic.c
index c7f6d1cab6063a6483802ee6c80391c18c2de884..d9a09bdd09db656891aa51f910753b686dc79964 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
+#include <linux/module.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include "hda_codec.h"
@@ -47,7 +48,7 @@ int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
        mutex_init(&spec->pcm_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
+EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
 
 struct snd_kcontrol_new *
 snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
@@ -65,7 +66,7 @@ snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
                return NULL;
        return knew;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
+EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
 
 static void free_kctls(struct hda_gen_spec *spec)
 {
@@ -86,7 +87,7 @@ void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
        snd_array_free(&spec->paths);
        snd_array_free(&spec->loopback_list);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
+EXPORT_SYMBOL_GPL(snd_hda_gen_spec_free);
 
 /*
  * store user hints
@@ -266,7 +267,7 @@ struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
 {
        return get_nid_path(codec, from_nid, to_nid, 0);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
+EXPORT_SYMBOL_GPL(snd_hda_get_nid_path);
 
 /* get the index number corresponding to the path instance;
  * the index starts from 1, for easier checking the invalid value
@@ -284,7 +285,7 @@ int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
                return 0;
        return idx + 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_path_idx);
+EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
 
 /* get the path instance corresponding to the given index number */
 struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
@@ -295,7 +296,7 @@ struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
                return NULL;
        return snd_array_elem(&spec->paths, idx - 1);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_path_from_idx);
+EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
 
 /* check whether the given DAC is already found in any existing paths */
 static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
@@ -432,7 +433,7 @@ bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
        }
        return false;
 }
-EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
+EXPORT_SYMBOL_GPL(snd_hda_parse_nid_path);
 
 /*
  * parse the path between the given NIDs and add to the path list.
@@ -463,7 +464,7 @@ snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
        spec->paths.used--;
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
+EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
 
 /* clear the given path as invalid so that it won't be picked up later */
 static void invalidate_nid_path(struct hda_codec *codec, int idx)
@@ -773,7 +774,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
        if (enable)
                path->active = true;
 }
-EXPORT_SYMBOL_HDA(snd_hda_activate_path);
+EXPORT_SYMBOL_GPL(snd_hda_activate_path);
 
 /* if the given path is inactive, put widgets into D3 (only if suitable) */
 static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
@@ -1149,7 +1150,7 @@ const struct badness_table hda_main_out_badness = {
        .shared_clfe = BAD_SHARED_CLFE,
        .shared_surr_main = BAD_SHARED_SURROUND,
 };
-EXPORT_SYMBOL_HDA(hda_main_out_badness);
+EXPORT_SYMBOL_GPL(hda_main_out_badness);
 
 const struct badness_table hda_extra_out_badness = {
        .no_primary_dac = BAD_NO_DAC,
@@ -1159,7 +1160,7 @@ const struct badness_table hda_extra_out_badness = {
        .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
        .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
 };
-EXPORT_SYMBOL_HDA(hda_extra_out_badness);
+EXPORT_SYMBOL_GPL(hda_extra_out_badness);
 
 /* get the DAC of the primary output corresponding to the given array index */
 static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
@@ -2857,9 +2858,11 @@ static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
        if (num_conns < idx)
                return false;
        nid = list[idx];
-       if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
+       if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
+           !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
                *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-       if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
+       if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
+           !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
                *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
 
        return *mix_val || *mute_val;
@@ -3053,6 +3056,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
                        spec->imux_pins[imux->num_items] = pin;
                        snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
                        imux_added = true;
+                       if (spec->dyn_adc_switch)
+                               spec->dyn_adc_idx[imux_idx] = c;
                }
        }
 
@@ -3150,7 +3155,9 @@ static int create_input_ctls(struct hda_codec *codec)
                }
        }
 
-       if (mixer && spec->add_stereo_mix_input) {
+       /* add stereo mix when explicitly enabled via hint */
+       if (mixer && spec->add_stereo_mix_input &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
                err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
                                           "Stereo Mix", 0);
                if (err < 0)
@@ -3262,7 +3269,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        snd_hda_codec_flush_cache(codec); /* flush the updates */
        if (err >= 0 && spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, ucontrol);
+               spec->cap_sync_hook(codec, kcontrol, ucontrol);
        return err;
 }
 
@@ -3383,7 +3390,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
                return ret;
 
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, ucontrol);
+               spec->cap_sync_hook(codec, kcontrol, ucontrol);
 
        return ret;
 }
@@ -3788,7 +3795,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
                return 0;
        snd_hda_activate_path(codec, path, true, false);
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, NULL);
+               spec->cap_sync_hook(codec, NULL, NULL);
        path_power_down_sync(codec, old_path);
        return 1;
 }
@@ -3916,7 +3923,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
        do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                    spec->autocfg.line_out_pins, paths, on);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
+EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
 
 static void call_update_outputs(struct hda_codec *codec)
 {
@@ -3949,7 +3956,7 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
                return;
        call_update_outputs(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
+EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
 
 /* standard line-out-automute helper */
 void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -3969,7 +3976,7 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac
                return;
        call_update_outputs(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
+EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
 
 /* standard mic auto-switch helper */
 void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -3992,7 +3999,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
        }
        mux_select(codec, 0, spec->am_entry[0].idx);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
+EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
 
 /* call appropriate hooks */
 static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -4305,11 +4312,11 @@ static int check_auto_mic_availability(struct hda_codec *codec)
 }
 
 /* power_filter hook; make inactive widgets into power down */
-static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
+unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
                                                  hda_nid_t nid,
                                                  unsigned int power_state)
 {
-       if (power_state != AC_PWRST_D0)
+       if (power_state != AC_PWRST_D0 || nid == codec->afg)
                return power_state;
        if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
                return power_state;
@@ -4317,6 +4324,7 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
                return power_state;
        return AC_PWRST_D3;
 }
+EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
 
 /* mute all aamix inputs initially; parse up to the first leaves */
 static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
@@ -4374,7 +4382,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                        spec->no_analog = 1;
                        goto dig_only;
                }
-               return 0; /* can't find valid BIOS pin config */
+               if (!cfg->num_inputs && !cfg->dig_in_pin)
+                       return 0; /* can't find valid BIOS pin config */
        }
 
        if (!spec->no_primary_hp &&
@@ -4442,6 +4451,19 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
 
+       /* add stereo mix if available and not enabled yet */
+       if (!spec->auto_mic && spec->mixer_nid &&
+           spec->add_stereo_mix_input &&
+           spec->input_mux.num_items > 1 &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
+               err = parse_capture_source(codec, spec->mixer_nid,
+                                          CFG_IDX_MIX, spec->num_all_adcs,
+                                          "Stereo Mix", 0);
+               if (err < 0)
+                       return err;
+       }
+
+
        err = create_capture_mixers(codec);
        if (err < 0)
                return err;
@@ -4494,7 +4516,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
+EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
 
 
 /*
@@ -4576,7 +4598,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
+EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
 
 
 /*
@@ -5109,7 +5131,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
+EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
 
 
 /*
@@ -5183,6 +5205,23 @@ static void init_multi_io(struct hda_codec *codec)
        }
 }
 
+static void init_aamix_paths(struct hda_codec *codec)
+{
+       struct hda_gen_spec *spec = codec->spec;
+
+       if (!spec->have_aamix_ctl)
+               return;
+       update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
+                          spec->aamix_out_paths[0],
+                          spec->autocfg.line_out_type);
+       update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
+                          spec->aamix_out_paths[1],
+                          AUTO_PIN_HP_OUT);
+       update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
+                          spec->aamix_out_paths[2],
+                          AUTO_PIN_SPEAKER_OUT);
+}
+
 /* set up input pins and loopback paths */
 static void init_analog_input(struct hda_codec *codec)
 {
@@ -5231,7 +5270,7 @@ static void init_input_src(struct hda_codec *codec)
        }
 
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, NULL);
+               spec->cap_sync_hook(codec, NULL, NULL);
 }
 
 /* set right pin controls for digital I/O */
@@ -5285,6 +5324,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        init_multi_out(codec);
        init_extra_out(codec);
        init_multi_io(codec);
+       init_aamix_paths(codec);
        init_analog_input(codec);
        init_input_src(codec);
        init_digital(codec);
@@ -5302,7 +5342,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        hda_call_check_power_status(codec, 0x01);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_init);
+EXPORT_SYMBOL_GPL(snd_hda_gen_init);
 
 /*
  * free the generic spec;
@@ -5315,7 +5355,7 @@ void snd_hda_gen_free(struct hda_codec *codec)
        kfree(codec->spec);
        codec->spec = NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_free);
+EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
 #ifdef CONFIG_PM
 /*
@@ -5327,7 +5367,7 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
        struct hda_gen_spec *spec = codec->spec;
        return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
+EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
 #endif
 
 
@@ -5372,4 +5412,7 @@ error:
        snd_hda_gen_free(codec);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
+EXPORT_SYMBOL_GPL(snd_hda_parse_generic_codec);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic HD-audio codec parser");