aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index af2c8943b303..853e5c786c37 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1533,6 +1533,43 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
1533} 1533}
1534 1534
1535/* 1535/*
1536 * SPDIF sharing with analog output
1537 */
1538static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
1539 struct snd_ctl_elem_value *ucontrol)
1540{
1541 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
1542 ucontrol->value.integer.value[0] = mout->share_spdif;
1543 return 0;
1544}
1545
1546static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
1547 struct snd_ctl_elem_value *ucontrol)
1548{
1549 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
1550 mout->share_spdif = !!ucontrol->value.integer.value[0];
1551 return 0;
1552}
1553
1554static struct snd_kcontrol_new spdif_share_sw = {
1555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1556 .name = "IEC958 Default PCM Playback Switch",
1557 .info = snd_ctl_boolean_mono_info,
1558 .get = spdif_share_sw_get,
1559 .put = spdif_share_sw_put,
1560};
1561
1562int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
1563 struct hda_multi_out *mout)
1564{
1565 if (!mout->dig_out_nid)
1566 return 0;
1567 /* ATTENTION: here mout is passed as private_data, instead of codec */
1568 return snd_ctl_add(codec->bus->card,
1569 snd_ctl_new1(&spdif_share_sw, mout));
1570}
1571
1572/*
1536 * SPDIF input 1573 * SPDIF input
1537 */ 1574 */
1538 1575
@@ -2557,9 +2594,36 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
2557 */ 2594 */
2558int snd_hda_multi_out_analog_open(struct hda_codec *codec, 2595int snd_hda_multi_out_analog_open(struct hda_codec *codec,
2559 struct hda_multi_out *mout, 2596 struct hda_multi_out *mout,
2560 struct snd_pcm_substream *substream) 2597 struct snd_pcm_substream *substream,
2561{ 2598 struct hda_pcm_stream *hinfo)
2562 substream->runtime->hw.channels_max = mout->max_channels; 2599{
2600 struct snd_pcm_runtime *runtime = substream->runtime;
2601 runtime->hw.channels_max = mout->max_channels;
2602 if (mout->dig_out_nid) {
2603 if (!mout->analog_rates) {
2604 mout->analog_rates = hinfo->rates;
2605 mout->analog_formats = hinfo->formats;
2606 mout->analog_maxbps = hinfo->maxbps;
2607 } else {
2608 runtime->hw.rates = mout->analog_rates;
2609 runtime->hw.formats = mout->analog_formats;
2610 hinfo->maxbps = mout->analog_maxbps;
2611 }
2612 if (!mout->spdif_rates) {
2613 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
2614 &mout->spdif_rates,
2615 &mout->spdif_formats,
2616 &mout->spdif_maxbps);
2617 }
2618 mutex_lock(&codec->spdif_mutex);
2619 if (mout->share_spdif) {
2620 runtime->hw.rates &= mout->spdif_rates;
2621 runtime->hw.formats &= mout->spdif_formats;
2622 if (mout->spdif_maxbps < hinfo->maxbps)
2623 hinfo->maxbps = mout->spdif_maxbps;
2624 }
2625 }
2626 mutex_unlock(&codec->spdif_mutex);
2563 return snd_pcm_hw_constraint_step(substream->runtime, 0, 2627 return snd_pcm_hw_constraint_step(substream->runtime, 0,
2564 SNDRV_PCM_HW_PARAM_CHANNELS, 2); 2628 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
2565} 2629}
@@ -2579,7 +2643,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
2579 int i; 2643 int i;
2580 2644
2581 mutex_lock(&codec->spdif_mutex); 2645 mutex_lock(&codec->spdif_mutex);
2582 if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { 2646 if (mout->dig_out_nid && mout->share_spdif &&
2647 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
2583 if (chs == 2 && 2648 if (chs == 2 &&
2584 snd_hda_is_supported_format(codec, mout->dig_out_nid, 2649 snd_hda_is_supported_format(codec, mout->dig_out_nid,
2585 format) && 2650 format) &&