diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 73 |
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 | */ | ||
1538 | static 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 | |||
1546 | static 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 | |||
1554 | static 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 | |||
1562 | int 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 | */ |
2558 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, | 2595 | int 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) && |