ALSA: hda - Pass bus io_ops directly from the top-level driver
[firefly-linux-kernel-4.4.55.git] / sound / pci / hda / hda_generic.c
index 0ef2459cd05fd6468a1ec6ee7d04a02bdb971fda..3d2597b7037bbc9c5a74faeeae035f5c5bd70f76 100644 (file)
@@ -654,7 +654,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
        int type = get_wcaps_type(get_wcaps(codec, nid));
        int i, n;
 
-       if (nid == codec->afg)
+       if (nid == codec->core.afg)
                return true;
 
        for (n = 0; n < spec->paths.used; n++) {
@@ -832,7 +832,9 @@ static hda_nid_t path_power_update(struct hda_codec *codec,
 
        for (i = 0; i < path->depth; i++) {
                nid = path->path[i];
-               if (nid == codec->afg)
+               if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
+                       continue;
+               if (nid == codec->core.afg)
                        continue;
                if (!allow_powerdown || is_active_nid_for_any(codec, nid))
                        state = AC_PWRST_D0;
@@ -842,10 +844,8 @@ static hda_nid_t path_power_update(struct hda_codec *codec,
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_POWER_STATE, state);
                        changed = nid;
-                       /* here we assume that widget attributes (e.g. amp,
-                        * pinctl connection) don't change with local power
-                        * state change.  If not, need to sync the cache.
-                        */
+                       if (state == AC_PWRST_D0)
+                               snd_hdac_regmap_sync_node(&codec->core, nid);
                }
        }
        return changed;
@@ -1897,12 +1897,11 @@ static void debug_show_configs(struct hda_codec *codec,
 static void fill_all_dac_nids(struct hda_codec *codec)
 {
        struct hda_gen_spec *spec = codec->spec;
-       int i;
-       hda_nid_t nid = codec->start_nid;
+       hda_nid_t nid;
 
        spec->num_all_dacs = 0;
        memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
-       for (i = 0; i < codec->num_nodes; i++, nid++) {
+       for_each_hda_codec_node(nid, codec) {
                if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
                        continue;
                if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
@@ -3067,10 +3066,9 @@ static int fill_adc_nids(struct hda_codec *codec)
        hda_nid_t nid;
        hda_nid_t *adc_nids = spec->adc_nids;
        int max_nums = ARRAY_SIZE(spec->adc_nids);
-       int i, nums = 0;
+       int nums = 0;
 
-       nid = codec->start_nid;
-       for (i = 0; i < codec->num_nodes; i++, nid++) {
+       for_each_hda_codec_node(nid, codec) {
                unsigned int caps = get_wcaps(codec, nid);
                int type = get_wcaps_type(caps);
 
@@ -3383,11 +3381,6 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
        imux = &spec->input_mux;
        adc_idx = kcontrol->id.index;
        mutex_lock(&codec->control_mutex);
-       /* we use the cache-only update at first since multiple input paths
-        * may shared the same amp; by updating only caches, the redundant
-        * writes to hardware can be reduced.
-        */
-       codec->cached_write = 1;
        for (i = 0; i < imux->num_items; i++) {
                path = get_input_path(codec, adc_idx, i);
                if (!path || !path->ctls[type])
@@ -3395,12 +3388,9 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
                kcontrol->private_value = path->ctls[type];
                err = func(kcontrol, ucontrol);
                if (err < 0)
-                       goto error;
+                       break;
        }
- error:
-       codec->cached_write = 0;
        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, kcontrol, ucontrol);
        return err;
@@ -3864,8 +3854,7 @@ static void parse_digital(struct hda_codec *codec)
 
        if (spec->autocfg.dig_in_pin) {
                pin = spec->autocfg.dig_in_pin;
-               dig_nid = codec->start_nid;
-               for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
+               for_each_hda_codec_node(dig_nid, codec) {
                        unsigned int wcaps = get_wcaps(codec, dig_nid);
                        if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
                                continue;
@@ -3970,6 +3959,14 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
        return changed;
 }
 
+/* check the jack status for power control */
+static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
+{
+       if (!is_jack_detectable(codec, pin))
+               return true;
+       return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
+}
+
 /* power up/down the paths of the given pin according to the jack state;
  * power = 0/1 : only power up/down if it matches with the jack state,
  *       < 0   : force power up/down to follow the jack sate
@@ -3984,7 +3981,8 @@ static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
        if (!codec->power_save_node)
                return 0;
 
-       on = snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
+       on = detect_pin_state(codec, pin);
+
        if (power >= 0 && on != power)
                return 0;
        return set_path_power(codec, pin, on, -1);
@@ -4236,8 +4234,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
                if (codec->power_save_node) {
                        bool on = !mute;
                        if (on)
-                               on = snd_hda_jack_detect_state(codec, nid)
-                                       != HDA_JACK_NOT_PRESENT;
+                               on = detect_pin_state(codec, nid);
                        set_path_power(codec, nid, on, -1);
                }
        }
@@ -4706,7 +4703,11 @@ 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 || nid == codec->afg)
+       struct hda_gen_spec *spec = codec->spec;
+
+       if (!spec->power_down_unused && !codec->power_save_node)
+               return power_state;
+       if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
                return power_state;
        if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
                return power_state;
@@ -4917,7 +4918,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
        parse_digital(codec);
 
        if (spec->power_down_unused || codec->power_save_node)
-               codec->power_filter = snd_hda_gen_path_power_filter;
+               if (!codec->power_filter)
+                       codec->power_filter = snd_hda_gen_path_power_filter;
 
        if (!spec->no_analog && spec->beep_nid) {
                err = snd_hda_attach_beep_device(codec, spec->beep_nid);
@@ -5478,7 +5480,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
 
        fill_pcm_stream_name(spec->stream_name_analog,
                             sizeof(spec->stream_name_analog),
-                            " Analog", codec->chip_name);
+                            " Analog", codec->core.chip_name);
        info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
        if (!info)
                return -ENOMEM;
@@ -5509,7 +5511,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
        if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
                fill_pcm_stream_name(spec->stream_name_digital,
                                     sizeof(spec->stream_name_digital),
-                                    " Digital", codec->chip_name);
+                                    " Digital", codec->core.chip_name);
                info = snd_hda_codec_pcm_new(codec, "%s",
                                             spec->stream_name_digital);
                if (!info)
@@ -5544,7 +5546,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
        if (spec->alt_dac_nid || have_multi_adcs) {
                fill_pcm_stream_name(spec->stream_name_alt_analog,
                                     sizeof(spec->stream_name_alt_analog),
-                            " Alt Analog", codec->chip_name);
+                            " Alt Analog", codec->core.chip_name);
                info = snd_hda_codec_pcm_new(codec, "%s",
                                             spec->stream_name_alt_analog);
                if (!info)
@@ -5763,8 +5765,6 @@ int snd_hda_gen_init(struct hda_codec *codec)
 
        snd_hda_apply_verbs(codec);
 
-       codec->cached_write = 1;
-
        init_multi_out(codec);
        init_extra_out(codec);
        init_multi_io(codec);
@@ -5780,7 +5780,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        /* call init functions of standard auto-mute helpers */
        update_automute_all(codec);
 
-       snd_hda_codec_flush_cache(codec);
+       regcache_sync(codec->core.regmap);
 
        if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
                snd_hda_sync_vmaster_hook(&spec->vmaster_mute);