aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-07 11:54:34 +0100
committerTakashi Iwai <tiwai@suse.de>2013-01-12 08:43:52 +0100
commite6b85f3c9d5ea3807dee651c28d5b0d5982ae2fa (patch)
treed92d1da51d487dcaa18966427b1ce09285dd3d82 /sound/pci/hda/hda_generic.c
parentc2c803830a5d9897344cd3ffd82daddd7f9f3864 (diff)
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: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 296628b6ffc..28ad5e98b34 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3261,6 +3261,16 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
* 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
*/
@@ -3275,8 +3285,11 @@ static int playback_pcm_open(struct hda_pcm_stream *hinfo,
err = snd_hda_multi_out_analog_open(codec,
&spec->multiout, substream,
hinfo);
- if (!err)
+ if (!err) {
spec->active_streams |= 1 << STREAM_MULTI_OUT;
+ call_pcm_playback_hook(hinfo, codec, substream,
+ HDA_GEN_PCM_ACT_OPEN);
+ }
mutex_unlock(&spec->pcm_mutex);
return err;
}
@@ -3288,8 +3301,14 @@ static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct hda_gen_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
- stream_tag, format, substream);
+ int err;
+
+ err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
+ 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,
@@ -3297,7 +3316,13 @@ static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
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,
@@ -3307,6 +3332,8 @@ static int playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_gen_spec *spec = codec->spec;
mutex_lock(&spec->pcm_mutex);
spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
+ call_pcm_playback_hook(hinfo, codec, substream,
+ HDA_GEN_PCM_ACT_CLOSE);
mutex_unlock(&spec->pcm_mutex);
return 0;
}
@@ -3323,6 +3350,8 @@ static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
err = -EBUSY;
else
spec->active_streams |= 1 << STREAM_INDEP_HP;
+ call_pcm_playback_hook(hinfo, codec, substream,
+ HDA_GEN_PCM_ACT_OPEN);
mutex_unlock(&spec->pcm_mutex);
return err;
}
@@ -3334,10 +3363,34 @@ static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_gen_spec *spec = codec->spec;
mutex_lock(&spec->pcm_mutex);
spec->active_streams &= ~(1 << STREAM_INDEP_HP);
+ call_pcm_playback_hook(hinfo, codec, substream,
+ HDA_GEN_PCM_ACT_CLOSE);
mutex_unlock(&spec->pcm_mutex);
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
*/
@@ -3432,7 +3485,9 @@ static const struct hda_pcm_stream pcm_analog_alt_playback = {
/* NID is set in build_pcms */
.ops = {
.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
},
};