aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c73
-rw-r--r--sound/pci/hda/hda_local.h13
-rw-r--r--sound/pci/hda/patch_analog.c8
-rw-r--r--sound/pci/hda/patch_cmedia.c8
-rw-r--r--sound/pci/hda/patch_conexant.c8
-rw-r--r--sound/pci/hda/patch_realtek.c8
-rw-r--r--sound/pci/hda/patch_sigmatel.c8
-rw-r--r--sound/pci/hda/patch_via.c8
8 files changed, 123 insertions, 11 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) &&
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ad0014ab71f9..ce2ad42a8a8a 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -228,8 +228,18 @@ struct hda_multi_out {
228 int max_channels; /* currently supported analog channels */ 228 int max_channels; /* currently supported analog channels */
229 int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ 229 int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
230 int no_share_stream; /* don't share a stream with multiple pins */ 230 int no_share_stream; /* don't share a stream with multiple pins */
231 int share_spdif; /* share SPDIF pin */
232 /* PCM information for both analog and SPDIF DACs */
233 unsigned int analog_rates;
234 unsigned int analog_maxbps;
235 u64 analog_formats;
236 unsigned int spdif_rates;
237 unsigned int spdif_maxbps;
238 u64 spdif_formats;
231}; 239};
232 240
241int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
242 struct hda_multi_out *mout);
233int snd_hda_multi_out_dig_open(struct hda_codec *codec, 243int snd_hda_multi_out_dig_open(struct hda_codec *codec,
234 struct hda_multi_out *mout); 244 struct hda_multi_out *mout);
235int snd_hda_multi_out_dig_close(struct hda_codec *codec, 245int snd_hda_multi_out_dig_close(struct hda_codec *codec,
@@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
241 struct snd_pcm_substream *substream); 251 struct snd_pcm_substream *substream);
242int snd_hda_multi_out_analog_open(struct hda_codec *codec, 252int snd_hda_multi_out_analog_open(struct hda_codec *codec,
243 struct hda_multi_out *mout, 253 struct hda_multi_out *mout,
244 struct snd_pcm_substream *substream); 254 struct snd_pcm_substream *substream,
255 struct hda_pcm_stream *hinfo);
245int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, 256int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
246 struct hda_multi_out *mout, 257 struct hda_multi_out *mout,
247 unsigned int stream_tag, 258 unsigned int stream_tag,
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 266c35e32b64..1f2102860fe8 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -171,6 +171,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
171 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 171 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
172 if (err < 0) 172 if (err < 0)
173 return err; 173 return err;
174 err = snd_hda_create_spdif_share_sw(codec,
175 &spec->multiout);
176 if (err < 0)
177 return err;
178 spec->multiout.share_spdif = 1;
174 } 179 }
175 if (spec->dig_in_nid) { 180 if (spec->dig_in_nid) {
176 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 181 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -217,7 +222,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
217 struct snd_pcm_substream *substream) 222 struct snd_pcm_substream *substream)
218{ 223{
219 struct ad198x_spec *spec = codec->spec; 224 struct ad198x_spec *spec = codec->spec;
220 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 225 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
226 hinfo);
221} 227}
222 228
223static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 229static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 99ce74b4e9fc..9794d4166ae4 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -329,6 +329,11 @@ static int cmi9880_build_controls(struct hda_codec *codec)
329 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 329 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
330 if (err < 0) 330 if (err < 0)
331 return err; 331 return err;
332 err = snd_hda_create_spdif_share_sw(codec,
333 &spec->multiout);
334 if (err < 0)
335 return err;
336 spec->multiout.share_spdif = 1;
332 } 337 }
333 if (spec->dig_in_nid) { 338 if (spec->dig_in_nid) {
334 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 339 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -432,7 +437,8 @@ static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
432 struct snd_pcm_substream *substream) 437 struct snd_pcm_substream *substream)
433{ 438{
434 struct cmi_spec *spec = codec->spec; 439 struct cmi_spec *spec = codec->spec;
435 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 440 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
441 hinfo);
436} 442}
437 443
438static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 444static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index bb915ede0ceb..2bb9a58db9fa 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -98,7 +98,8 @@ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
98 struct snd_pcm_substream *substream) 98 struct snd_pcm_substream *substream)
99{ 99{
100 struct conexant_spec *spec = codec->spec; 100 struct conexant_spec *spec = codec->spec;
101 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 101 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
102 hinfo);
102} 103}
103 104
104static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 105static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -372,6 +373,11 @@ static int conexant_build_controls(struct hda_codec *codec)
372 spec->multiout.dig_out_nid); 373 spec->multiout.dig_out_nid);
373 if (err < 0) 374 if (err < 0)
374 return err; 375 return err;
376 err = snd_hda_create_spdif_share_sw(codec,
377 &spec->multiout);
378 if (err < 0)
379 return err;
380 spec->multiout.share_spdif = 1;
375 } 381 }
376 if (spec->dig_in_nid) { 382 if (spec->dig_in_nid) {
377 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); 383 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d41eafacd86d..6c605813fc6e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1520,6 +1520,11 @@ static int alc_build_controls(struct hda_codec *codec)
1520 spec->multiout.dig_out_nid); 1520 spec->multiout.dig_out_nid);
1521 if (err < 0) 1521 if (err < 0)
1522 return err; 1522 return err;
1523 err = snd_hda_create_spdif_share_sw(codec,
1524 &spec->multiout);
1525 if (err < 0)
1526 return err;
1527 spec->multiout.share_spdif = 1;
1523 } 1528 }
1524 if (spec->dig_in_nid) { 1529 if (spec->dig_in_nid) {
1525 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 1530 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -2325,7 +2330,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
2325 struct snd_pcm_substream *substream) 2330 struct snd_pcm_substream *substream)
2326{ 2331{
2327 struct alc_spec *spec = codec->spec; 2332 struct alc_spec *spec = codec->spec;
2328 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 2333 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2334 hinfo);
2329} 2335}
2330 2336
2331static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2337static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7f506ef0accb..7901e76f2690 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -916,6 +916,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
916 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 916 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
917 if (err < 0) 917 if (err < 0)
918 return err; 918 return err;
919 err = snd_hda_create_spdif_share_sw(codec,
920 &spec->multiout);
921 if (err < 0)
922 return err;
923 spec->multiout.share_spdif = 1;
919 } 924 }
920 if (spec->dig_in_nid) { 925 if (spec->dig_in_nid) {
921 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 926 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -1748,7 +1753,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
1748 struct snd_pcm_substream *substream) 1753 struct snd_pcm_substream *substream)
1749{ 1754{
1750 struct sigmatel_spec *spec = codec->spec; 1755 struct sigmatel_spec *spec = codec->spec;
1751 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 1756 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
1757 hinfo);
1752} 1758}
1753 1759
1754static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 1760static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index d9a5c6a2dd9f..3515a3fb5d9d 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
357 struct snd_pcm_substream *substream) 357 struct snd_pcm_substream *substream)
358{ 358{
359 struct via_spec *spec = codec->spec; 359 struct via_spec *spec = codec->spec;
360 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 360 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
361 hinfo);
361} 362}
362 363
363static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 364static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -493,6 +494,11 @@ static int via_build_controls(struct hda_codec *codec)
493 spec->multiout.dig_out_nid); 494 spec->multiout.dig_out_nid);
494 if (err < 0) 495 if (err < 0)
495 return err; 496 return err;
497 err = snd_hda_create_spdif_share_sw(codec,
498 &spec->multiout);
499 if (err < 0)
500 return err;
501 spec->multiout.share_spdif = 1;
496 } 502 }
497 if (spec->dig_in_nid) { 503 if (spec->dig_in_nid) {
498 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 504 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);