Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c125ba3b authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda-alc-mute' into topic/hda

parents 7a2e38a5 a68d5a54
Loading
Loading
Loading
Loading
+56 −12
Original line number Diff line number Diff line
@@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache)
}

/* query the hash.  allocate an entry if not found. */
static struct hda_cache_head  *get_alloc_hash(struct hda_cache_rec *cache,
					      u32 key)
static struct hda_cache_head  *get_hash(struct hda_cache_rec *cache, u32 key)
{
	u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
	u16 cur = cache->hash[idx];
@@ -1222,7 +1221,16 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
			return info;
		cur = info->next;
	}
	return NULL;
}

/* query the hash.  allocate an entry if not found. */
static struct hda_cache_head  *get_alloc_hash(struct hda_cache_rec *cache,
					      u32 key)
{
	struct hda_cache_head *info = get_hash(cache, key);
	if (!info) {
		u16 idx, cur;
		/* add a new hash entry */
		info = snd_array_new(&cache->buf);
		if (!info)
@@ -1230,9 +1238,10 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
		cur = snd_array_index(&cache->buf, info);
		info->key = key;
		info->val = 0;
		idx = key % (u16)ARRAY_SIZE(cache->hash);
		info->next = cache->hash[idx];
		cache->hash[idx] = cur;

	}
	return info;
}

@@ -2721,6 +2730,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);

/**
 * snd_hda_codec_update_cache - check cache and write the cmd only when needed
 * @codec: the HDA codec
 * @nid: NID to send the command
 * @direct: direct flag
 * @verb: the verb to send
 * @parm: the parameter for the verb
 *
 * This function works like snd_hda_codec_write_cache(), but it doesn't send
 * command if the parameter is already identical with the cached value.
 * If not, it sends the command and refreshes the cache.
 *
 * Returns 0 if successful, or a negative error code.
 */
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
			       int direct, unsigned int verb, unsigned int parm)
{
	struct hda_cache_head *c;
	u32 key;

	/* parm may contain the verb stuff for get/set amp */
	verb = verb | (parm >> 8);
	parm &= 0xff;
	key = build_cmd_cache_key(nid, verb);
	mutex_lock(&codec->bus->cmd_mutex);
	c = get_hash(&codec->cmd_cache, key);
	if (c && c->val == parm) {
		mutex_unlock(&codec->bus->cmd_mutex);
		return 0;
	}
	mutex_unlock(&codec->bus->cmd_mutex);
	return snd_hda_codec_write_cache(codec, nid, direct, verb, parm);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);

/**
 * snd_hda_codec_resume_cache - Resume the all commands from the cache
 * @codec: HD-audio codec
+3 −0
Original line number Diff line number Diff line
@@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
			      int direct, 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 direct, unsigned int verb, unsigned int parm);
void snd_hda_codec_resume_cache(struct hda_codec *codec);
#else
#define snd_hda_codec_write_cache	snd_hda_codec_write
#define snd_hda_codec_update_cache	snd_hda_codec_write
#define snd_hda_sequence_write_cache	snd_hda_sequence_write
#endif

+39 −0
Original line number Diff line number Diff line
@@ -3467,6 +3467,10 @@ static int alc_init(struct hda_codec *codec)
	if (spec->init_hook)
		spec->init_hook(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (codec->patch_ops.check_power_status)
		codec->patch_ops.check_power_status(codec, 0x01);
#endif
	return 0;
}
@@ -3827,6 +3831,10 @@ static int alc_resume(struct hda_codec *codec)
	codec->patch_ops.init(codec);
	snd_hda_codec_resume_amp(codec);
	snd_hda_codec_resume_cache(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (codec->patch_ops.check_power_status)
		codec->patch_ops.check_power_status(codec, 0x01);
#endif
	return 0;
}
#endif
@@ -13983,6 +13991,35 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
	/* NID is set in alc_build_pcms */
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
static int alc269_mic2_for_mute_led(struct hda_codec *codec)
{
	switch (codec->subsystem_id) {
	case 0x103c1586:
		return 1;
	}
	return 0;
}
static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
{
	/* update mute-LED according to the speaker mute state */
	if (nid == 0x01 || nid == 0x14) {
		int pinval;
		if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
		    HDA_AMP_MUTE)
			pinval = 0x24;
		else
			pinval = 0x20;
		/* mic2 vref pin is used for mute LED control */
		snd_hda_codec_update_cache(codec, 0x19, 0,
					   AC_VERB_SET_PIN_WIDGET_CONTROL,
					   pinval);
	}
	return alc_check_power_status(codec, nid);
}
#endif /* CONFIG_SND_HDA_POWER_SAVE */
/*
 * BIOS auto configuration
 */
@@ -14330,6 +14367,8 @@ static int patch_alc269(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (!spec->loopback.amplist)
		spec->loopback.amplist = alc269_loopbacks;
	if (alc269_mic2_for_mute_led(codec))
		codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
#endif
	return 0;