From: Takashi Iwai Date: Sat, 18 Jun 2011 14:40:14 +0000 (+0200) Subject: ALSA: hda - Assign HP-independent PCM to individual stream X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=7eb56e84e6c4deaa552db96834ea0b233ba92f50;p=linux-beck.git ALSA: hda - Assign HP-independent PCM to individual stream Instead of using the secondary substream, create an individual PCM stream for HP-independent PCM. Otherwise it's difficult to handle different channel numbers with multi-channel stream in the sam PCM stream structure. Signed-off-by: Takashi Iwai --- diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 18f2a135c026..264889c9c177 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -122,6 +122,7 @@ struct via_spec { unsigned int num_iverbs; char stream_name_analog[32]; + char stream_name_hp[32]; const struct hda_pcm_stream *stream_analog_playback; const struct hda_pcm_stream *stream_analog_capture; @@ -1210,14 +1211,20 @@ static const struct hda_verb vt1708_volume_init_verbs[] = { { } }; +static void substream_set_idle(struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + int idle = substream->pstr->substream_opened == 1 + && substream->ref_count == 0; + analog_low_current_mode(codec, idle); +} + static int via_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { struct via_spec *spec = codec->spec; - int idle = substream->pstr->substream_opened == 1 - && substream->ref_count == 0; - analog_low_current_mode(codec, idle); + substream_set_idle(codec, substream); return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, hinfo); } @@ -1226,17 +1233,29 @@ static int via_playback_pcm_close(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - int idle = substream->pstr->substream_opened == 1 - && substream->ref_count == 0; + substream_set_idle(codec, substream); + return 0; +} - analog_low_current_mode(codec, idle); +static int via_playback_hp_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct via_spec *spec = codec->spec; + struct hda_multi_out *mout = &spec->multiout; + + if (!mout->hp_nid || mout->hp_nid == mout->dac_nids[HDA_FRONT] || + !spec->hp_independent_mode) + return -EINVAL; + substream_set_idle(codec, substream); return 0; } -static void playback_multi_pcm_prep_0(struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) +static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) { struct via_spec *spec = codec->spec; struct hda_multi_out *mout = &spec->multiout; @@ -1301,27 +1320,20 @@ static void playback_multi_pcm_prep_0(struct hda_codec *codec, snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } + vt1708_start_hp_work(spec); + return 0; } -static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) +static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) { struct via_spec *spec = codec->spec; struct hda_multi_out *mout = &spec->multiout; - const hda_nid_t *nids = mout->dac_nids; - if (substream->number == 0) - playback_multi_pcm_prep_0(codec, stream_tag, format, - substream); - else { - if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] && - spec->hp_independent_mode) - snd_hda_codec_setup_stream(codec, mout->hp_nid, - stream_tag, 0, format); - } + snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); vt1708_start_hp_work(spec); return 0; } @@ -1335,33 +1347,38 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, const hda_nid_t *nids = mout->dac_nids; int i; - if (substream->number == 0) { - for (i = 0; i < mout->num_dacs; i++) - snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); + for (i = 0; i < mout->num_dacs; i++) + snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); - if (mout->hp_nid && !spec->hp_independent_mode) - snd_hda_codec_setup_stream(codec, mout->hp_nid, - 0, 0, 0); + if (mout->hp_nid && !spec->hp_independent_mode) + snd_hda_codec_setup_stream(codec, mout->hp_nid, + 0, 0, 0); - for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) - if (mout->extra_out_nid[i]) - snd_hda_codec_setup_stream(codec, - mout->extra_out_nid[i], - 0, 0, 0); - mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_nid && - mout->dig_out_used == HDA_DIG_ANALOG_DUP) { - snd_hda_codec_setup_stream(codec, mout->dig_out_nid, - 0, 0, 0); - mout->dig_out_used = 0; - } - mutex_unlock(&codec->spdif_mutex); - } else { - if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] && - spec->hp_independent_mode) - snd_hda_codec_setup_stream(codec, mout->hp_nid, + for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) + if (mout->extra_out_nid[i]) + snd_hda_codec_setup_stream(codec, + mout->extra_out_nid[i], 0, 0, 0); + mutex_lock(&codec->spdif_mutex); + if (mout->dig_out_nid && + mout->dig_out_used == HDA_DIG_ANALOG_DUP) { + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, + 0, 0, 0); + mout->dig_out_used = 0; } + mutex_unlock(&codec->spdif_mutex); + vt1708_stop_hp_work(spec); + return 0; +} + +static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct via_spec *spec = codec->spec; + struct hda_multi_out *mout = &spec->multiout; + + snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); vt1708_stop_hp_work(spec); return 0; } @@ -1431,7 +1448,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, } static const struct hda_pcm_stream via_pcm_analog_playback = { - .substreams = 2, /* will be changed in via_build_pcms() */ + .substreams = 1, .channels_min = 2, .channels_max = 8, /* NID is set in via_build_pcms */ @@ -1443,8 +1460,21 @@ static const struct hda_pcm_stream via_pcm_analog_playback = { }, }; +static const struct hda_pcm_stream via_pcm_hp_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in via_build_pcms */ + .ops = { + .open = via_playback_hp_pcm_open, + .close = via_playback_pcm_close, + .prepare = via_playback_hp_pcm_prepare, + .cleanup = via_playback_hp_pcm_cleanup + }, +}; + static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { - .substreams = 2, /* will be changed in via_build_pcms() */ + .substreams = 1, .channels_min = 2, .channels_max = 8, /* NID is set in via_build_pcms */ @@ -1462,7 +1492,7 @@ static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { }; static const struct hda_pcm_stream via_pcm_analog_capture = { - .substreams = 2, /* will be changed in via_build_pcms() */ + .substreams = 1, /* will be changed in via_build_pcms() */ .channels_min = 2, .channels_max = 2, /* NID is set in via_build_pcms */ @@ -1577,8 +1607,6 @@ static int via_build_pcms(struct hda_codec *codec) spec->multiout.dac_nids[0]; info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - if (!spec->multiout.hp_nid) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 1; if (!spec->stream_analog_capture) spec->stream_analog_capture = &via_pcm_analog_capture; @@ -1616,6 +1644,16 @@ static int via_build_pcms(struct hda_codec *codec) } } + if (spec->multiout.hp_nid) { + codec->num_pcms++; + info++; + snprintf(spec->stream_name_hp, sizeof(spec->stream_name_hp), + "%s HP", codec->chip_name); + info->name = spec->stream_name_hp; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = via_pcm_hp_playback; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = + spec->multiout.hp_nid; + } return 0; }