diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 144 |
1 files changed, 13 insertions, 131 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 52962f697825..b27f250088c1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -929,9 +929,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) | |||
929 | codec->proc_widget_hook = NULL; | 929 | codec->proc_widget_hook = NULL; |
930 | codec->spec = NULL; | 930 | codec->spec = NULL; |
931 | 931 | ||
932 | free_hda_cache(&codec->amp_cache); | ||
933 | free_hda_cache(&codec->cmd_cache); | 932 | free_hda_cache(&codec->cmd_cache); |
934 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | ||
935 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 933 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
936 | 934 | ||
937 | /* free only driver_pins so that init_pins + user_pins are restored */ | 935 | /* free only driver_pins so that init_pins + user_pins are restored */ |
@@ -996,7 +994,6 @@ static void snd_hda_codec_dev_release(struct device *dev) | |||
996 | free_init_pincfgs(codec); | 994 | free_init_pincfgs(codec); |
997 | snd_hdac_device_exit(&codec->core); | 995 | snd_hdac_device_exit(&codec->core); |
998 | snd_hda_sysfs_clear(codec); | 996 | snd_hda_sysfs_clear(codec); |
999 | free_hda_cache(&codec->amp_cache); | ||
1000 | free_hda_cache(&codec->cmd_cache); | 997 | free_hda_cache(&codec->cmd_cache); |
1001 | kfree(codec->modelname); | 998 | kfree(codec->modelname); |
1002 | kfree(codec->wcaps); | 999 | kfree(codec->wcaps); |
@@ -1051,7 +1048,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, | |||
1051 | mutex_init(&codec->spdif_mutex); | 1048 | mutex_init(&codec->spdif_mutex); |
1052 | mutex_init(&codec->control_mutex); | 1049 | mutex_init(&codec->control_mutex); |
1053 | mutex_init(&codec->hash_mutex); | 1050 | mutex_init(&codec->hash_mutex); |
1054 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | ||
1055 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1051 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
1056 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); | 1052 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1057 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | 1053 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); |
@@ -1380,67 +1376,6 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
1380 | return info; | 1376 | return info; |
1381 | } | 1377 | } |
1382 | 1378 | ||
1383 | /* query and allocate an amp hash entry */ | ||
1384 | static inline struct hda_amp_info * | ||
1385 | get_alloc_amp_hash(struct hda_codec *codec, u32 key) | ||
1386 | { | ||
1387 | return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); | ||
1388 | } | ||
1389 | |||
1390 | /* overwrite the value with the key in the caps hash */ | ||
1391 | static int write_caps_hash(struct hda_codec *codec, u32 key, unsigned int val) | ||
1392 | { | ||
1393 | struct hda_amp_info *info; | ||
1394 | |||
1395 | mutex_lock(&codec->hash_mutex); | ||
1396 | info = get_alloc_amp_hash(codec, key); | ||
1397 | if (!info) { | ||
1398 | mutex_unlock(&codec->hash_mutex); | ||
1399 | return -EINVAL; | ||
1400 | } | ||
1401 | info->amp_caps = val; | ||
1402 | info->head.val |= INFO_AMP_CAPS; | ||
1403 | mutex_unlock(&codec->hash_mutex); | ||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | /* query the value from the caps hash; if not found, fetch the current | ||
1408 | * value from the given function and store in the hash | ||
1409 | */ | ||
1410 | static unsigned int | ||
1411 | query_caps_hash(struct hda_codec *codec, hda_nid_t nid, int dir, u32 key, | ||
1412 | unsigned int (*func)(struct hda_codec *, hda_nid_t, int)) | ||
1413 | { | ||
1414 | struct hda_amp_info *info; | ||
1415 | unsigned int val; | ||
1416 | |||
1417 | mutex_lock(&codec->hash_mutex); | ||
1418 | info = get_alloc_amp_hash(codec, key); | ||
1419 | if (!info) { | ||
1420 | mutex_unlock(&codec->hash_mutex); | ||
1421 | return 0; | ||
1422 | } | ||
1423 | if (!(info->head.val & INFO_AMP_CAPS)) { | ||
1424 | mutex_unlock(&codec->hash_mutex); /* for reentrance */ | ||
1425 | val = func(codec, nid, dir); | ||
1426 | write_caps_hash(codec, key, val); | ||
1427 | } else { | ||
1428 | val = info->amp_caps; | ||
1429 | mutex_unlock(&codec->hash_mutex); | ||
1430 | } | ||
1431 | return val; | ||
1432 | } | ||
1433 | |||
1434 | static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid, | ||
1435 | int direction) | ||
1436 | { | ||
1437 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) | ||
1438 | nid = codec->core.afg; | ||
1439 | return snd_hda_param_read(codec, nid, | ||
1440 | direction == HDA_OUTPUT ? | ||
1441 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | ||
1442 | } | ||
1443 | |||
1444 | /** | 1379 | /** |
1445 | * query_amp_caps - query AMP capabilities | 1380 | * query_amp_caps - query AMP capabilities |
1446 | * @codec: the HD-auio codec | 1381 | * @codec: the HD-auio codec |
@@ -1455,9 +1390,11 @@ static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid, | |||
1455 | */ | 1390 | */ |
1456 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | 1391 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) |
1457 | { | 1392 | { |
1458 | return query_caps_hash(codec, nid, direction, | 1393 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) |
1459 | HDA_HASH_KEY(nid, direction, 0), | 1394 | nid = codec->core.afg; |
1460 | read_amp_cap); | 1395 | return snd_hda_param_read(codec, nid, |
1396 | direction == HDA_OUTPUT ? | ||
1397 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | ||
1461 | } | 1398 | } |
1462 | EXPORT_SYMBOL_GPL(query_amp_caps); | 1399 | EXPORT_SYMBOL_GPL(query_amp_caps); |
1463 | 1400 | ||
@@ -1498,50 +1435,14 @@ EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps); | |||
1498 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 1435 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
1499 | unsigned int caps) | 1436 | unsigned int caps) |
1500 | { | 1437 | { |
1501 | return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps); | 1438 | unsigned int parm; |
1502 | } | ||
1503 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); | ||
1504 | |||
1505 | static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid, | ||
1506 | int dir) | ||
1507 | { | ||
1508 | return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1509 | } | ||
1510 | |||
1511 | /** | ||
1512 | * snd_hda_query_pin_caps - Query PIN capabilities | ||
1513 | * @codec: the HD-auio codec | ||
1514 | * @nid: the NID to query | ||
1515 | * | ||
1516 | * Query PIN capabilities for the given widget. | ||
1517 | * Returns the obtained capability bits. | ||
1518 | * | ||
1519 | * When cap bits have been already read, this doesn't read again but | ||
1520 | * returns the cached value. | ||
1521 | */ | ||
1522 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
1523 | { | ||
1524 | return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid), | ||
1525 | read_pin_cap); | ||
1526 | } | ||
1527 | EXPORT_SYMBOL_GPL(snd_hda_query_pin_caps); | ||
1528 | 1439 | ||
1529 | /** | 1440 | snd_hda_override_wcaps(codec, nid, |
1530 | * snd_hda_override_pin_caps - Override the pin capabilities | 1441 | get_wcaps(codec, nid) | AC_WCAP_AMP_OVRD); |
1531 | * @codec: the CODEC | 1442 | parm = dir == HDA_OUTPUT ? AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP; |
1532 | * @nid: the NID to override | 1443 | return snd_hdac_override_parm(&codec->core, nid, parm, caps); |
1533 | * @caps: the capability bits to set | ||
1534 | * | ||
1535 | * Override the cached PIN capabilitiy bits value by the given one. | ||
1536 | * | ||
1537 | * Returns zero if successful or a negative error code. | ||
1538 | */ | ||
1539 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | ||
1540 | unsigned int caps) | ||
1541 | { | ||
1542 | return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps); | ||
1543 | } | 1444 | } |
1544 | EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps); | 1445 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); |
1545 | 1446 | ||
1546 | /** | 1447 | /** |
1547 | * snd_hda_codec_amp_stereo - update the AMP stereo values | 1448 | * snd_hda_codec_amp_stereo - update the AMP stereo values |
@@ -3462,11 +3363,6 @@ static void hda_mark_cmd_cache_dirty(struct hda_codec *codec) | |||
3462 | cmd = snd_array_elem(&codec->cmd_cache.buf, i); | 3363 | cmd = snd_array_elem(&codec->cmd_cache.buf, i); |
3463 | cmd->dirty = 1; | 3364 | cmd->dirty = 1; |
3464 | } | 3365 | } |
3465 | for (i = 0; i < codec->amp_cache.buf.used; i++) { | ||
3466 | struct hda_amp_info *amp; | ||
3467 | amp = snd_array_elem(&codec->amp_cache.buf, i); | ||
3468 | amp->head.dirty = 1; | ||
3469 | } | ||
3470 | } | 3366 | } |
3471 | 3367 | ||
3472 | /* | 3368 | /* |
@@ -3714,8 +3610,7 @@ unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, | |||
3714 | } | 3610 | } |
3715 | EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); | 3611 | EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); |
3716 | 3612 | ||
3717 | static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid, | 3613 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) |
3718 | int dir) | ||
3719 | { | 3614 | { |
3720 | unsigned int val = 0; | 3615 | unsigned int val = 0; |
3721 | if (nid != codec->core.afg && | 3616 | if (nid != codec->core.afg && |
@@ -3728,14 +3623,7 @@ static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid, | |||
3728 | return val; | 3623 | return val; |
3729 | } | 3624 | } |
3730 | 3625 | ||
3731 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) | 3626 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) |
3732 | { | ||
3733 | return query_caps_hash(codec, nid, 0, HDA_HASH_PARPCM_KEY(nid), | ||
3734 | get_pcm_param); | ||
3735 | } | ||
3736 | |||
3737 | static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid, | ||
3738 | int dir) | ||
3739 | { | 3627 | { |
3740 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 3628 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
3741 | if (!streams || streams == -1) | 3629 | if (!streams || streams == -1) |
@@ -3745,12 +3633,6 @@ static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid, | |||
3745 | return streams; | 3633 | return streams; |
3746 | } | 3634 | } |
3747 | 3635 | ||
3748 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) | ||
3749 | { | ||
3750 | return query_caps_hash(codec, nid, 0, HDA_HASH_PARSTR_KEY(nid), | ||
3751 | get_stream_param); | ||
3752 | } | ||
3753 | |||
3754 | /** | 3636 | /** |
3755 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | 3637 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats |
3756 | * @codec: the HDA codec | 3638 | * @codec: the HDA codec |