aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c52
-rw-r--r--sound/pci/hda/hda_codec.h1
2 files changed, 51 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4f3291150809..696d77e575ec 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1454,12 +1454,22 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1454 codec->spdif_ctls = val; 1454 codec->spdif_ctls = val;
1455 1455
1456 if (change) { 1456 if (change) {
1457 hda_nid_t *d;
1457 snd_hda_codec_write_cache(codec, nid, 0, 1458 snd_hda_codec_write_cache(codec, nid, 0,
1458 AC_VERB_SET_DIGI_CONVERT_1, 1459 AC_VERB_SET_DIGI_CONVERT_1,
1459 val & 0xff); 1460 val & 0xff);
1460 snd_hda_codec_write_cache(codec, nid, 0, 1461 snd_hda_codec_write_cache(codec, nid, 0,
1461 AC_VERB_SET_DIGI_CONVERT_2, 1462 AC_VERB_SET_DIGI_CONVERT_2,
1462 val >> 8); 1463 val >> 8);
1464
1465 for (d = codec->slave_dig_outs; *d; d++) {
1466 snd_hda_codec_write_cache(codec, *d, 0,
1467 AC_VERB_SET_DIGI_CONVERT_1,
1468 val & 0xff);
1469 snd_hda_codec_write_cache(codec, *d, 0,
1470 AC_VERB_SET_DIGI_CONVERT_2,
1471 val >> 8);
1472 }
1463 } 1473 }
1464 1474
1465 mutex_unlock(&codec->spdif_mutex); 1475 mutex_unlock(&codec->spdif_mutex);
@@ -1491,10 +1501,16 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1491 val |= AC_DIG1_ENABLE; 1501 val |= AC_DIG1_ENABLE;
1492 change = codec->spdif_ctls != val; 1502 change = codec->spdif_ctls != val;
1493 if (change) { 1503 if (change) {
1504 hda_nid_t *d;
1494 codec->spdif_ctls = val; 1505 codec->spdif_ctls = val;
1495 snd_hda_codec_write_cache(codec, nid, 0, 1506 snd_hda_codec_write_cache(codec, nid, 0,
1496 AC_VERB_SET_DIGI_CONVERT_1, 1507 AC_VERB_SET_DIGI_CONVERT_1,
1497 val & 0xff); 1508 val & 0xff);
1509
1510 for (d = codec->slave_dig_outs; *d; d++)
1511 snd_hda_codec_write_cache(codec, *d, 0,
1512 AC_VERB_SET_DIGI_CONVERT_1,
1513 val & 0xff);
1498 /* unmute amp switch (if any) */ 1514 /* unmute amp switch (if any) */
1499 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && 1515 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
1500 (val & AC_DIG1_ENABLE)) 1516 (val & AC_DIG1_ENABLE))
@@ -1643,9 +1659,14 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
1643 mutex_lock(&codec->spdif_mutex); 1659 mutex_lock(&codec->spdif_mutex);
1644 change = codec->spdif_in_enable != val; 1660 change = codec->spdif_in_enable != val;
1645 if (change) { 1661 if (change) {
1662 hda_nid_t *d;
1646 codec->spdif_in_enable = val; 1663 codec->spdif_in_enable = val;
1647 snd_hda_codec_write_cache(codec, nid, 0, 1664 snd_hda_codec_write_cache(codec, nid, 0,
1648 AC_VERB_SET_DIGI_CONVERT_1, val); 1665 AC_VERB_SET_DIGI_CONVERT_1, val);
1666
1667 for (d = codec->slave_dig_outs; *d; d++)
1668 snd_hda_codec_write_cache(codec, *d, 0,
1669 AC_VERB_SET_DIGI_CONVERT_1, val);
1649 } 1670 }
1650 mutex_unlock(&codec->spdif_mutex); 1671 mutex_unlock(&codec->spdif_mutex);
1651 return change; 1672 return change;
@@ -2589,15 +2610,30 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
2589static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, 2610static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
2590 unsigned int stream_tag, unsigned int format) 2611 unsigned int stream_tag, unsigned int format)
2591{ 2612{
2613 hda_nid_t *d;
2614
2592 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ 2615 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
2593 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) 2616 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
2594 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 2617 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
2618 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
2619
2620 for (d = codec->slave_dig_outs; *d; d++)
2621 snd_hda_codec_write(codec, *d, 0,
2622 AC_VERB_SET_DIGI_CONVERT_1,
2595 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); 2623 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
2624 }
2596 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); 2625 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
2597 /* turn on again (if needed) */ 2626 /* turn on again (if needed) */
2598 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) 2627 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
2599 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 2628 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
2600 codec->spdif_ctls & 0xff); 2629 codec->spdif_ctls & 0xff);
2630
2631 for (d = codec->slave_dig_outs; *d; d++)
2632 snd_hda_codec_write(codec, *d, 0,
2633 AC_VERB_SET_DIGI_CONVERT_1,
2634 codec->spdif_ctls & 0xff);
2635 }
2636
2601} 2637}
2602 2638
2603/* 2639/*
@@ -2621,8 +2657,12 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
2621 unsigned int format, 2657 unsigned int format,
2622 struct snd_pcm_substream *substream) 2658 struct snd_pcm_substream *substream)
2623{ 2659{
2660 hda_nid_t *nid;
2624 mutex_lock(&codec->spdif_mutex); 2661 mutex_lock(&codec->spdif_mutex);
2625 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); 2662 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
2663 if (codec->slave_dig_outs)
2664 for (nid = codec->slave_dig_outs; *nid; nid++)
2665 setup_dig_out_stream(codec, *nid, stream_tag, format);
2626 mutex_unlock(&codec->spdif_mutex); 2666 mutex_unlock(&codec->spdif_mutex);
2627 return 0; 2667 return 0;
2628} 2668}
@@ -2689,6 +2729,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
2689 struct snd_pcm_substream *substream) 2729 struct snd_pcm_substream *substream)
2690{ 2730{
2691 hda_nid_t *nids = mout->dac_nids; 2731 hda_nid_t *nids = mout->dac_nids;
2732 hda_nid_t *d;
2692 int chs = substream->runtime->channels; 2733 int chs = substream->runtime->channels;
2693 int i; 2734 int i;
2694 2735
@@ -2702,9 +2743,16 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
2702 mout->dig_out_used = HDA_DIG_ANALOG_DUP; 2743 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
2703 setup_dig_out_stream(codec, mout->dig_out_nid, 2744 setup_dig_out_stream(codec, mout->dig_out_nid,
2704 stream_tag, format); 2745 stream_tag, format);
2746 if (codec->slave_dig_outs)
2747 for (d = codec->slave_dig_outs; *d; d++)
2748 setup_dig_out_stream(codec, *d,
2749 stream_tag, format);
2705 } else { 2750 } else {
2706 mout->dig_out_used = 0; 2751 mout->dig_out_used = 0;
2707 snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); 2752 snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
2753 if (codec->slave_dig_outs)
2754 for (d = codec->slave_dig_outs; *d; d++)
2755 snd_hda_codec_cleanup_stream(codec, *d);
2708 } 2756 }
2709 } 2757 }
2710 mutex_unlock(&codec->spdif_mutex); 2758 mutex_unlock(&codec->spdif_mutex);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 780e2fffae3a..60468f562400 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -725,6 +725,7 @@ struct hda_codec {
725 unsigned int spdif_status; /* IEC958 status bits */ 725 unsigned int spdif_status; /* IEC958 status bits */
726 unsigned short spdif_ctls; /* SPDIF control bits */ 726 unsigned short spdif_ctls; /* SPDIF control bits */
727 unsigned int spdif_in_enable; /* SPDIF input enable? */ 727 unsigned int spdif_in_enable; /* SPDIF input enable? */
728 hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
728 729
729 struct snd_hwdep *hwdep; /* assigned hwdep device */ 730 struct snd_hwdep *hwdep; /* assigned hwdep device */
730 731