Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353009
b: refs/heads/master
c: c370dd6
h: refs/heads/master
i:
  353007: e43c32a
v: v3
  • Loading branch information
Takashi Iwai committed Jan 12, 2013
1 parent c9f11fc commit f92fa4a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8092e6065435d75a68873fa66cd003a1b829e0fe
refs/heads/master: c370dd6e9faae4b2e699a1f210827aceaa0c3399
77 changes: 61 additions & 16 deletions trunk/sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,7 @@ 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;
info->dirty = 0;
idx = key % (u16)ARRAY_SIZE(cache->hash);
info->next = cache->hash[idx];
cache->hash[idx] = cur;
Expand Down Expand Up @@ -1873,8 +1874,11 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
return 0;
}
info->vol[ch] = val;
if (codec->cached_write)
info->head.dirty = 1;
mutex_unlock(&codec->hash_mutex);
put_vol_mute(codec, info, nid, ch, direction, idx, val);
if (!codec->cached_write)
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Expand Down Expand Up @@ -1905,7 +1909,6 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);

#ifdef CONFIG_PM
/**
* snd_hda_codec_resume_amp - Resume all AMP commands from the cache
* @codec: HD-audio codec
Expand All @@ -1914,13 +1917,17 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
*/
void snd_hda_codec_resume_amp(struct hda_codec *codec)
{
struct hda_amp_info *buffer = codec->amp_cache.buf.list;
int i;

for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
u32 key = buffer->head.key;
mutex_lock(&codec->hash_mutex);
for (i = 0; i < codec->amp_cache.buf.used; i++) {
struct hda_amp_info *buffer;
u32 key;
hda_nid_t nid;
unsigned int idx, dir, ch;

buffer = snd_array_elem(&codec->amp_cache.buf, i);
key = buffer->head.key;
if (!key)
continue;
nid = key & 0xff;
Expand All @@ -1929,13 +1936,18 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
for (ch = 0; ch < 2; ch++) {
if (!(buffer->head.val & INFO_AMP_VOL(ch)))
continue;
if (!buffer->head.dirty)
continue;
buffer->head.dirty = 0;
mutex_unlock(&codec->hash_mutex);
put_vol_mute(codec, buffer, nid, ch, dir, idx,
buffer->vol[ch]);
mutex_lock(&codec->hash_mutex);
}
}
mutex_unlock(&codec->hash_mutex);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
#endif /* CONFIG_PM */

static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int ofs)
Expand Down Expand Up @@ -3375,12 +3387,11 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
}
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);

#ifdef CONFIG_PM
/*
* command cache
*/

/* build a 32bit cache key with the widget id and the command parameter */
/* build a 31bit cache key with the widget id and the command parameter */
#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
#define get_cmd_cache_nid(key) ((key) & 0xff)
#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
Expand All @@ -3400,20 +3411,27 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
int direct, unsigned int verb, unsigned int parm)
{
int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
int err;
struct hda_cache_head *c;
u32 key;

if (err < 0)
return err;
if (!codec->cached_write) {
err = snd_hda_codec_write(codec, nid, direct, verb, parm);
if (err < 0)
return err;
}

/* 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_alloc_hash(&codec->cmd_cache, key);
if (c)
if (c) {
c->val = parm;
if (codec->cached_write)
c->dirty = 1;
}
mutex_unlock(&codec->bus->cmd_mutex);
return 0;
}
Expand Down Expand Up @@ -3462,16 +3480,26 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
*/
void snd_hda_codec_resume_cache(struct hda_codec *codec)
{
struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
int i;

for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
u32 key = buffer->key;
mutex_lock(&codec->hash_mutex);
for (i = 0; i < codec->cmd_cache.buf.used; i++) {
struct hda_cache_head *buffer;
u32 key;

buffer = snd_array_elem(&codec->cmd_cache.buf, i);
key = buffer->key;
if (!key)
continue;
if (!buffer->dirty)
continue;
buffer->dirty = 0;
mutex_unlock(&codec->hash_mutex);
snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
get_cmd_cache_cmd(key), buffer->val);
mutex_lock(&codec->hash_mutex);
}
mutex_unlock(&codec->hash_mutex);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);

Expand All @@ -3492,7 +3520,6 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
seq->param);
}
EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
#endif /* CONFIG_PM */

void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state,
Expand Down Expand Up @@ -3640,13 +3667,31 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
return state;
}

/* mark all entries of cmd and amp caches dirty */
static void hda_mark_cmd_cache_dirty(struct hda_codec *codec)
{
int i;
for (i = 0; i < codec->cmd_cache.buf.used; i++) {
struct hda_cache_head *cmd;
cmd = snd_array_elem(&codec->cmd_cache.buf, i);
cmd->dirty = 1;
}
for (i = 0; i < codec->amp_cache.buf.used; i++) {
struct hda_amp_info *amp;
amp = snd_array_elem(&codec->cmd_cache.buf, i);
amp->head.dirty = 1;
}
}

/*
* kick up codec; used both from PM and power-save
*/
static void hda_call_codec_resume(struct hda_codec *codec)
{
codec->in_pm = 1;

hda_mark_cmd_cache_dirty(codec);

/* set as if powered on for avoiding re-entering the resume
* in the resume / power-save sequence
*/
Expand Down
12 changes: 4 additions & 8 deletions trunk/sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,9 +719,10 @@ struct hda_codec_ops {

/* record for amp information cache */
struct hda_cache_head {
u32 key; /* hash key */
u32 key:31; /* hash key */
u32 dirty:1;
u16 val; /* assigned value */
u16 next; /* next link; -1 = terminal */
u16 next;
};

struct hda_amp_info {
Expand Down Expand Up @@ -867,6 +868,7 @@ struct hda_codec {
unsigned int no_jack_detect:1; /* Machine has no jack-detection */
unsigned int pcm_format_first:1; /* PCM format must be set first */
unsigned int epss:1; /* supporting EPSS? */
unsigned int cached_write:1; /* write only to caches */
#ifdef CONFIG_PM
unsigned int power_on :1; /* current (global) power-state */
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
Expand Down Expand Up @@ -952,19 +954,13 @@ void snd_hda_sequence_write(struct hda_codec *codec,
int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);

/* cached write */
#ifdef CONFIG_PM
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

/* the struct for codec->pin_configs */
struct hda_pincfg {
Expand Down
2 changes: 0 additions & 2 deletions trunk/sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val);
#ifdef CONFIG_PM
void snd_hda_codec_resume_amp(struct hda_codec *codec);
#endif

void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv);
Expand Down

0 comments on commit f92fa4a

Please sign in to comment.