Commit a551d914 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Use regmap for command verb caches, too

Like the previous patches, this patch converts also to the regmap, at
this time, the cached verb writes are the target.  But this conversion
needs a bit more caution than before.

- In the old code, we just record any verbs as is, and restore them at
  resume.  For the regmap scheme, this doesn't work, since a few verbs
  like AMP or DIGI_CONVERT are asymmetrical.  Such verbs are converted
  either to the dedicated function (snd_hda_regmap_xxx_amp()) or
  changed to the unified verb.

- Some verbs have to be declared as vendor-specific ones before
  accessing via regmap.

Also, the minor optimization with codec->cached_write flag is dropped
in a few places, as this would confuse the operation.  Further
optimizations will be brought in the later patches, if any.

This conversion ends up with a drop of significant amount of codes,
mostly the helper codes that are no longer used.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5e56bcea
This diff is collapsed.
......@@ -155,19 +155,6 @@ struct hda_codec_ops {
void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on);
};
/* record for amp information cache */
struct hda_cache_head {
u32 key:31; /* hash key */
u32 dirty:1;
u16 val; /* assigned value */
u16 next;
};
struct hda_cache_rec {
u16 hash[64]; /* hash table for index */
struct snd_array buf; /* record entries */
};
/* PCM callbacks */
struct hda_pcm_ops {
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
......@@ -251,13 +238,10 @@ struct hda_codec {
struct snd_array mixers; /* list of assigned mixer elements */
struct snd_array nids; /* list of mapped mixer elements */
struct hda_cache_rec cmd_cache; /* cache for other commands */
struct list_head conn_list; /* linked-list of connection-list */
struct mutex spdif_mutex;
struct mutex control_mutex;
struct mutex hash_mutex;
struct snd_array spdif_out;
unsigned int spdif_in_enable; /* SPDIF input enable? */
const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
......@@ -406,15 +390,15 @@ snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
}
/* cached write */
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
int flags, unsigned int verb, unsigned int parm);
void snd_hda_sequence_write_cache(struct hda_codec *codec,
const struct hda_verb *seq);
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
int flags, unsigned int verb, unsigned int parm);
void snd_hda_codec_resume_cache(struct hda_codec *codec);
/* both for cmd & amp caches */
void snd_hda_codec_flush_cache(struct hda_codec *codec);
static inline int
snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
int flags, unsigned int verb, unsigned int parm)
{
return snd_hdac_regmap_write(&codec->core, nid, verb, parm);
}
#define snd_hda_codec_update_cache(codec, nid, flags, verb, parm) \
snd_hda_codec_write_cache(codec, nid, flags, verb, parm)
/* the struct for codec->pin_configs */
struct hda_pincfg {
......
......@@ -3381,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])
......@@ -3393,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;
......@@ -5760,8 +5752,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);
......@@ -5777,7 +5767,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);
......
......@@ -777,7 +777,6 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
return 0;
mutex_lock(&codec->control_mutex);
codec->cached_write = 1;
path = snd_hda_get_path_from_idx(codec,
spec->smux_paths[spec->cur_smux]);
if (path)
......@@ -786,9 +785,7 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
if (path)
snd_hda_activate_path(codec, path, true, true);
spec->cur_smux = val;
codec->cached_write = 0;
mutex_unlock(&codec->control_mutex);
snd_hda_codec_flush_cache(codec); /* flush the updates */
return 1;
}
......@@ -1004,18 +1001,17 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct ad198x_spec *spec = codec->spec;
static const struct hda_verb gpio_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
{},
};
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
spec->gen.own_eapd_ctl = 1;
snd_hda_sequence_write_cache(codec, gpio_init_verbs);
snd_hda_codec_write_cache(codec, 0x01, 0,
AC_VERB_SET_GPIO_MASK, 0x02);
snd_hda_codec_write_cache(codec, 0x01, 0,
AC_VERB_SET_GPIO_DIRECTION, 0x02);
snd_hda_codec_write_cache(codec, 0x01, 0,
AC_VERB_SET_GPIO_DATA, 0x02);
break;
case HDA_FIXUP_ACT_PROBE:
if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
......
......@@ -302,6 +302,7 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec,
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC;
snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410);
break;
case HDA_FIXUP_ACT_PROBE:
spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
......@@ -409,15 +410,11 @@ static void olpc_xo_automic(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
struct conexant_spec *spec = codec->spec;
int saved_cached_write = codec->cached_write;
codec->cached_write = 1;
/* in DC mode, we don't handle automic */
if (!spec->dc_enable)
snd_hda_gen_mic_autoswitch(codec, jack);
olpc_xo_update_mic_pins(codec);
snd_hda_codec_flush_cache(codec);
codec->cached_write = saved_cached_write;
if (spec->dc_enable)
olpc_xo_update_mic_boost(codec);
}
......
......@@ -2212,7 +2212,6 @@ static int generic_hdmi_resume(struct hda_codec *codec)
codec->patch_ops.init(codec);
regcache_sync(codec->core.regmap);
snd_hda_codec_resume_cache(codec);
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
......@@ -2299,6 +2298,7 @@ static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
/* enable DP1.2 mode */
vendor_param |= INTEL_EN_DP12;
snd_hdac_regmap_add_vendor_verb(&codec->core, INTEL_SET_VENDOR_VERB);
snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0,
INTEL_SET_VENDOR_VERB, vendor_param);
}
......
......@@ -800,7 +800,6 @@ static int alc_resume(struct hda_codec *codec)
msleep(150); /* to avoid pop noise */
codec->patch_ops.init(codec);
regcache_sync(codec->core.regmap);
snd_hda_codec_resume_cache(codec);
hda_call_check_power_status(codec, 0x01);
return 0;
}
......@@ -3059,7 +3058,6 @@ static int alc269_resume(struct hda_codec *codec)
}
regcache_sync(codec->core.regmap);
snd_hda_codec_resume_cache(codec);
hda_call_check_power_status(codec, 0x01);
/* on some machine, the BIOS will clear the codec gpio data when enter
......
......@@ -222,6 +222,10 @@ static int si3054_init(struct hda_codec *codec)
unsigned wait_count;
u16 val;
if (snd_hdac_regmap_add_vendor_verb(&codec->core,
SI3054_VERB_WRITE_NODE))
return -ENOMEM;
snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
snd_hda_codec_write(codec, codec->core.mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0);
SET_REG(codec, SI3054_LINE_RATE, 9600);
......
......@@ -1050,12 +1050,9 @@ static const struct hda_verb stac92hd71bxx_core_init[] = {
{}
};
static const struct hda_verb stac92hd71bxx_unmute_core_init[] = {
static const hda_nid_t stac92hd71bxx_unmute_nids[] = {
/* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{}
0x0f, 0x0a, 0x0d, 0
};
static const struct hda_verb stac925x_core_init[] = {
......@@ -4269,6 +4266,10 @@ static int stac_parse_auto_config(struct hda_codec *codec)
if (spec->aloopback_ctl &&
snd_hda_get_bool_hint(codec, "loopback") == 1) {
unsigned int wr_verb =
spec->aloopback_ctl->private_value >> 16;
if (snd_hdac_regmap_add_vendor_verb(&codec->core, wr_verb))
return -ENOMEM;
if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl))
return -ENOMEM;
}
......@@ -4688,7 +4689,7 @@ static int patch_stac92hd95(struct hda_codec *codec)
static int patch_stac92hd71bxx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
const hda_nid_t *unmute_nids = stac92hd71bxx_unmute_nids;
int err;
err = alloc_stac_spec(codec);
......@@ -4713,7 +4714,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x111d76b6: /* 4 Port without Analog Mixer */
case 0x111d76b7:
unmute_init++;
unmute_nids++;
break;
case 0x111d7608: /* 5 Port with Analog Mixer */
if ((codec->core.revision_id & 0xf) == 0 ||
......@@ -4721,7 +4722,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
spec->stream_delay = 40; /* 40 milliseconds */
/* disable VSW */
unmute_init++;
unmute_nids++;
snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
break;
......@@ -4735,8 +4736,12 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB)
snd_hda_add_verbs(codec, stac92hd71bxx_core_init);
if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
snd_hda_sequence_write_cache(codec, unmute_init);
if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) {
const hda_nid_t *p;
for (p = unmute_nids; *p; p++)
snd_hda_codec_amp_init_stereo(codec, *p, HDA_INPUT, 0,
0xff, 0x00);
}
spec->aloopback_ctl = &stac92hd71bxx_loopback;
spec->aloopback_mask = 0x50;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment