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.c113
1 files changed, 73 insertions, 40 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d2e1093f8e9..6447754ae56 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -94,6 +94,9 @@ static const struct hda_codec_preset *hda_preset_tables[] = {
94#ifdef CONFIG_SND_HDA_CODEC_VIA 94#ifdef CONFIG_SND_HDA_CODEC_VIA
95 snd_hda_preset_via, 95 snd_hda_preset_via,
96#endif 96#endif
97#ifdef CONFIG_SND_HDA_CODEC_NVHDMI
98 snd_hda_preset_nvhdmi,
99#endif
97 NULL 100 NULL
98}; 101};
99 102
@@ -211,7 +214,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
211 unsigned int shift, num_elems, mask; 214 unsigned int shift, num_elems, mask;
212 hda_nid_t prev_nid; 215 hda_nid_t prev_nid;
213 216
214 snd_assert(conn_list && max_conns > 0, return -EINVAL); 217 if (snd_BUG_ON(!conn_list || max_conns <= 0))
218 return -EINVAL;
215 219
216 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); 220 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
217 if (parm & AC_CLIST_LONG) { 221 if (parm & AC_CLIST_LONG) {
@@ -313,7 +317,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
313} 317}
314 318
315/* 319/*
316 * process queueud unsolicited events 320 * process queued unsolicited events
317 */ 321 */
318static void process_unsol_events(struct work_struct *work) 322static void process_unsol_events(struct work_struct *work)
319{ 323{
@@ -407,8 +411,10 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
407 .dev_free = snd_hda_bus_dev_free, 411 .dev_free = snd_hda_bus_dev_free,
408 }; 412 };
409 413
410 snd_assert(temp, return -EINVAL); 414 if (snd_BUG_ON(!temp))
411 snd_assert(temp->ops.command && temp->ops.get_response, return -EINVAL); 415 return -EINVAL;
416 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
417 return -EINVAL;
412 418
413 if (busp) 419 if (busp)
414 *busp = NULL; 420 *busp = NULL;
@@ -585,11 +591,13 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
585 struct hda_codec **codecp) 591 struct hda_codec **codecp)
586{ 592{
587 struct hda_codec *codec; 593 struct hda_codec *codec;
588 char component[13]; 594 char component[31];
589 int err; 595 int err;
590 596
591 snd_assert(bus, return -EINVAL); 597 if (snd_BUG_ON(!bus))
592 snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); 598 return -EINVAL;
599 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
600 return -EINVAL;
593 601
594 if (bus->caddr_tbl[codec_addr]) { 602 if (bus->caddr_tbl[codec_addr]) {
595 snd_printk(KERN_ERR "hda_codec: " 603 snd_printk(KERN_ERR "hda_codec: "
@@ -688,7 +696,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
688 snd_hda_create_hwdep(codec); 696 snd_hda_create_hwdep(codec);
689#endif 697#endif
690 698
691 sprintf(component, "HDA:%08x", codec->vendor_id); 699 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id);
692 snd_component_add(codec->bus->card, component); 700 snd_component_add(codec->bus->card, component);
693 701
694 if (codecp) 702 if (codecp)
@@ -956,15 +964,6 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
956} 964}
957#endif /* SND_HDA_NEEDS_RESUME */ 965#endif /* SND_HDA_NEEDS_RESUME */
958 966
959/*
960 * AMP control callbacks
961 */
962/* retrieve parameters from private_value */
963#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
964#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
965#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
966#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
967
968/* volume */ 967/* volume */
969int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, 968int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
970 struct snd_ctl_elem_info *uinfo) 969 struct snd_ctl_elem_info *uinfo)
@@ -1430,6 +1429,29 @@ static unsigned int convert_to_spdif_status(unsigned short val)
1430 return sbits; 1429 return sbits;
1431} 1430}
1432 1431
1432/* set digital convert verbs both for the given NID and its slaves */
1433static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1434 int verb, int val)
1435{
1436 hda_nid_t *d;
1437
1438 snd_hda_codec_write(codec, nid, 0, verb, val);
1439 d = codec->slave_dig_outs;
1440 if (!d)
1441 return;
1442 for (; *d; d++)
1443 snd_hda_codec_write(codec, *d, 0, verb, val);
1444}
1445
1446static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1447 int dig1, int dig2)
1448{
1449 if (dig1 != -1)
1450 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1451 if (dig2 != -1)
1452 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1453}
1454
1433static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, 1455static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1434 struct snd_ctl_elem_value *ucontrol) 1456 struct snd_ctl_elem_value *ucontrol)
1435{ 1457{
@@ -1448,14 +1470,8 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1448 change = codec->spdif_ctls != val; 1470 change = codec->spdif_ctls != val;
1449 codec->spdif_ctls = val; 1471 codec->spdif_ctls = val;
1450 1472
1451 if (change) { 1473 if (change)
1452 snd_hda_codec_write_cache(codec, nid, 0, 1474 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
1453 AC_VERB_SET_DIGI_CONVERT_1,
1454 val & 0xff);
1455 snd_hda_codec_write_cache(codec, nid, 0,
1456 AC_VERB_SET_DIGI_CONVERT_2,
1457 val >> 8);
1458 }
1459 1475
1460 mutex_unlock(&codec->spdif_mutex); 1476 mutex_unlock(&codec->spdif_mutex);
1461 return change; 1477 return change;
@@ -1487,9 +1503,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1487 change = codec->spdif_ctls != val; 1503 change = codec->spdif_ctls != val;
1488 if (change) { 1504 if (change) {
1489 codec->spdif_ctls = val; 1505 codec->spdif_ctls = val;
1490 snd_hda_codec_write_cache(codec, nid, 0, 1506 set_dig_out_convert(codec, nid, val & 0xff, -1);
1491 AC_VERB_SET_DIGI_CONVERT_1,
1492 val & 0xff);
1493 /* unmute amp switch (if any) */ 1507 /* unmute amp switch (if any) */
1494 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && 1508 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
1495 (val & AC_DIG1_ENABLE)) 1509 (val & AC_DIG1_ENABLE))
@@ -2236,11 +2250,13 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec,
2236 if (info->ops.close == NULL) 2250 if (info->ops.close == NULL)
2237 info->ops.close = hda_pcm_default_open_close; 2251 info->ops.close = hda_pcm_default_open_close;
2238 if (info->ops.prepare == NULL) { 2252 if (info->ops.prepare == NULL) {
2239 snd_assert(info->nid, return -EINVAL); 2253 if (snd_BUG_ON(!info->nid))
2254 return -EINVAL;
2240 info->ops.prepare = hda_pcm_default_prepare; 2255 info->ops.prepare = hda_pcm_default_prepare;
2241 } 2256 }
2242 if (info->ops.cleanup == NULL) { 2257 if (info->ops.cleanup == NULL) {
2243 snd_assert(info->nid, return -EINVAL); 2258 if (snd_BUG_ON(!info->nid))
2259 return -EINVAL;
2244 info->ops.cleanup = hda_pcm_default_cleanup; 2260 info->ops.cleanup = hda_pcm_default_cleanup;
2245 } 2261 }
2246 return 0; 2262 return 0;
@@ -2583,14 +2599,31 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
2583 unsigned int stream_tag, unsigned int format) 2599 unsigned int stream_tag, unsigned int format)
2584{ 2600{
2585 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ 2601 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
2586 if (codec->spdif_ctls & AC_DIG1_ENABLE) 2602 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
2587 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 2603 set_dig_out_convert(codec, nid,
2588 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); 2604 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
2605 -1);
2589 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); 2606 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
2607 if (codec->slave_dig_outs) {
2608 hda_nid_t *d;
2609 for (d = codec->slave_dig_outs; *d; d++)
2610 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
2611 format);
2612 }
2590 /* turn on again (if needed) */ 2613 /* turn on again (if needed) */
2591 if (codec->spdif_ctls & AC_DIG1_ENABLE) 2614 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
2592 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 2615 set_dig_out_convert(codec, nid,
2593 codec->spdif_ctls & 0xff); 2616 codec->spdif_ctls & 0xff, -1);
2617}
2618
2619static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
2620{
2621 snd_hda_codec_cleanup_stream(codec, nid);
2622 if (codec->slave_dig_outs) {
2623 hda_nid_t *d;
2624 for (d = codec->slave_dig_outs; *d; d++)
2625 snd_hda_codec_cleanup_stream(codec, *d);
2626 }
2594} 2627}
2595 2628
2596/* 2629/*
@@ -2602,7 +2635,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
2602 mutex_lock(&codec->spdif_mutex); 2635 mutex_lock(&codec->spdif_mutex);
2603 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) 2636 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
2604 /* already opened as analog dup; reset it once */ 2637 /* already opened as analog dup; reset it once */
2605 snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); 2638 cleanup_dig_out_stream(codec, mout->dig_out_nid);
2606 mout->dig_out_used = HDA_DIG_EXCLUSIVE; 2639 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
2607 mutex_unlock(&codec->spdif_mutex); 2640 mutex_unlock(&codec->spdif_mutex);
2608 return 0; 2641 return 0;
@@ -2697,7 +2730,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
2697 stream_tag, format); 2730 stream_tag, format);
2698 } else { 2731 } else {
2699 mout->dig_out_used = 0; 2732 mout->dig_out_used = 0;
2700 snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); 2733 cleanup_dig_out_stream(codec, mout->dig_out_nid);
2701 } 2734 }
2702 } 2735 }
2703 mutex_unlock(&codec->spdif_mutex); 2736 mutex_unlock(&codec->spdif_mutex);
@@ -2748,7 +2781,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
2748 mout->extra_out_nid[i]); 2781 mout->extra_out_nid[i]);
2749 mutex_lock(&codec->spdif_mutex); 2782 mutex_lock(&codec->spdif_mutex);
2750 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { 2783 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
2751 snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); 2784 cleanup_dig_out_stream(codec, mout->dig_out_nid);
2752 mout->dig_out_used = 0; 2785 mout->dig_out_used = 0;
2753 } 2786 }
2754 mutex_unlock(&codec->spdif_mutex); 2787 mutex_unlock(&codec->spdif_mutex);
@@ -2756,7 +2789,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
2756} 2789}
2757 2790
2758/* 2791/*
2759 * Helper for automatic ping configuration 2792 * Helper for automatic pin configuration
2760 */ 2793 */
2761 2794
2762static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) 2795static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)