diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 113 |
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 | */ |
318 | static void process_unsol_events(struct work_struct *work) | 322 | static 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 */ |
969 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | 968 | int 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 */ | ||
1433 | static 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 | |||
1446 | static 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 | |||
1433 | static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, | 1455 | static 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 | |||
2619 | static 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 | ||
2762 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | 2795 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) |