Commit e6b85f3c authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Add pcm_playback_hook to hda_gen_spec

The new hook which is called at each PCM playback ops.
It can be used to control the codec-specific power-saving feature in
each codec driver.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c2c80383
...@@ -3261,6 +3261,16 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls); ...@@ -3261,6 +3261,16 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
* PCM definitions * PCM definitions
*/ */
static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action)
{
struct hda_gen_spec *spec = codec->spec;
if (spec->pcm_playback_hook)
spec->pcm_playback_hook(hinfo, codec, substream, action);
}
/* /*
* Analog playback callbacks * Analog playback callbacks
*/ */
...@@ -3275,8 +3285,11 @@ static int playback_pcm_open(struct hda_pcm_stream *hinfo, ...@@ -3275,8 +3285,11 @@ static int playback_pcm_open(struct hda_pcm_stream *hinfo,
err = snd_hda_multi_out_analog_open(codec, err = snd_hda_multi_out_analog_open(codec,
&spec->multiout, substream, &spec->multiout, substream,
hinfo); hinfo);
if (!err) if (!err) {
spec->active_streams |= 1 << STREAM_MULTI_OUT; spec->active_streams |= 1 << STREAM_MULTI_OUT;
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_OPEN);
}
mutex_unlock(&spec->pcm_mutex); mutex_unlock(&spec->pcm_mutex);
return err; return err;
} }
...@@ -3288,8 +3301,14 @@ static int playback_pcm_prepare(struct hda_pcm_stream *hinfo, ...@@ -3288,8 +3301,14 @@ static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, int err;
err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
stream_tag, format, substream); stream_tag, format, substream);
if (!err)
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_PREPARE);
return err;
} }
static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo, static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
...@@ -3297,7 +3316,13 @@ static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo, ...@@ -3297,7 +3316,13 @@ static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); int err;
err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
if (!err)
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_CLEANUP);
return err;
} }
static int playback_pcm_close(struct hda_pcm_stream *hinfo, static int playback_pcm_close(struct hda_pcm_stream *hinfo,
...@@ -3307,6 +3332,8 @@ static int playback_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -3307,6 +3332,8 @@ static int playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
mutex_lock(&spec->pcm_mutex); mutex_lock(&spec->pcm_mutex);
spec->active_streams &= ~(1 << STREAM_MULTI_OUT); spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_CLOSE);
mutex_unlock(&spec->pcm_mutex); mutex_unlock(&spec->pcm_mutex);
return 0; return 0;
} }
...@@ -3323,6 +3350,8 @@ static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo, ...@@ -3323,6 +3350,8 @@ static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
err = -EBUSY; err = -EBUSY;
else else
spec->active_streams |= 1 << STREAM_INDEP_HP; spec->active_streams |= 1 << STREAM_INDEP_HP;
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_OPEN);
mutex_unlock(&spec->pcm_mutex); mutex_unlock(&spec->pcm_mutex);
return err; return err;
} }
...@@ -3334,10 +3363,34 @@ static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -3334,10 +3363,34 @@ static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
mutex_lock(&spec->pcm_mutex); mutex_lock(&spec->pcm_mutex);
spec->active_streams &= ~(1 << STREAM_INDEP_HP); spec->active_streams &= ~(1 << STREAM_INDEP_HP);
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_CLOSE);
mutex_unlock(&spec->pcm_mutex); mutex_unlock(&spec->pcm_mutex);
return 0; return 0;
} }
static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream)
{
snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_PREPARE);
return 0;
}
static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
snd_hda_codec_cleanup_stream(codec, hinfo->nid);
call_pcm_playback_hook(hinfo, codec, substream,
HDA_GEN_PCM_ACT_CLEANUP);
return 0;
}
/* /*
* Digital out * Digital out
*/ */
...@@ -3432,7 +3485,9 @@ static const struct hda_pcm_stream pcm_analog_alt_playback = { ...@@ -3432,7 +3485,9 @@ static const struct hda_pcm_stream pcm_analog_alt_playback = {
/* NID is set in build_pcms */ /* NID is set in build_pcms */
.ops = { .ops = {
.open = alt_playback_pcm_open, .open = alt_playback_pcm_open,
.close = alt_playback_pcm_close .close = alt_playback_pcm_close,
.prepare = alt_playback_pcm_prepare,
.cleanup = alt_playback_pcm_cleanup
}, },
}; };
......
...@@ -69,6 +69,14 @@ struct automic_entry { ...@@ -69,6 +69,14 @@ struct automic_entry {
/* active stream id */ /* active stream id */
enum { STREAM_MULTI_OUT, STREAM_INDEP_HP }; enum { STREAM_MULTI_OUT, STREAM_INDEP_HP };
/* PCM hook action */
enum {
HDA_GEN_PCM_ACT_OPEN,
HDA_GEN_PCM_ACT_PREPARE,
HDA_GEN_PCM_ACT_CLEANUP,
HDA_GEN_PCM_ACT_CLOSE,
};
struct hda_gen_spec { struct hda_gen_spec {
char stream_name_analog[32]; /* analog PCM stream */ char stream_name_analog[32]; /* analog PCM stream */
const struct hda_pcm_stream *stream_analog_playback; const struct hda_pcm_stream *stream_analog_playback;
...@@ -191,6 +199,12 @@ struct hda_gen_spec { ...@@ -191,6 +199,12 @@ struct hda_gen_spec {
void (*automute_hook)(struct hda_codec *codec); void (*automute_hook)(struct hda_codec *codec);
void (*cap_sync_hook)(struct hda_codec *codec); void (*cap_sync_hook)(struct hda_codec *codec);
/* PCM playback hook */
void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action);
/* automute / autoswitch hooks */ /* automute / autoswitch hooks */
void (*hp_automute_hook)(struct hda_codec *codec, void (*hp_automute_hook)(struct hda_codec *codec,
struct hda_jack_tbl *tbl); struct hda_jack_tbl *tbl);
......
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