diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-04-04 06:15:32 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-04-04 06:16:30 -0400 |
commit | 664bc5c55923712a8aabd2a390ed7477325e32df (patch) | |
tree | 6382fd31d0fab7699fb2ff6b0501275700dd5b85 /sound/pci | |
parent | ffda568e8b4979c6a04bbdd92acfd93b5dc5e163 (diff) | |
parent | 9d82f9272ddd8492afdd721c9999171741be835b (diff) |
Merge branch 'topic/hda-regmap' into for-next
This merges the support of regmap in HD-audio infrastructure.
Many in-house cache codes in HD-audio driver are relaced with the
more standard regmap base now.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_bind.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 675 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 74 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 14 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 48 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 28 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 16 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 5 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 25 |
12 files changed, 164 insertions, 739 deletions
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 7b269c3237e3..00aa31c5f08e 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c | |||
@@ -75,6 +75,9 @@ static int hda_codec_driver_probe(struct device *dev) | |||
75 | err = codec_refresh_name(codec, codec->preset->name); | 75 | err = codec_refresh_name(codec, codec->preset->name); |
76 | if (err < 0) | 76 | if (err < 0) |
77 | goto error; | 77 | goto error; |
78 | err = snd_hdac_regmap_init(&codec->core); | ||
79 | if (err < 0) | ||
80 | goto error; | ||
78 | 81 | ||
79 | if (!try_module_get(owner)) { | 82 | if (!try_module_get(owner)) { |
80 | err = -EINVAL; | 83 | err = -EINVAL; |
@@ -98,6 +101,7 @@ static int hda_codec_driver_probe(struct device *dev) | |||
98 | snd_hda_codec_register(codec); | 101 | snd_hda_codec_register(codec); |
99 | } | 102 | } |
100 | 103 | ||
104 | codec->core.lazy_cache = true; | ||
101 | return 0; | 105 | return 0; |
102 | 106 | ||
103 | error_module: | 107 | error_module: |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 145cae7903b6..41851f9b48c1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -586,8 +586,8 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
586 | return -ENOMEM; | 586 | return -ENOMEM; |
587 | nid = codec->core.start_nid; | 587 | nid = codec->core.start_nid; |
588 | for (i = 0; i < codec->core.num_nodes; i++, nid++) | 588 | for (i = 0; i < codec->core.num_nodes; i++, nid++) |
589 | codec->wcaps[i] = snd_hda_param_read(codec, nid, | 589 | codec->wcaps[i] = snd_hdac_read_parm_uncached(&codec->core, |
590 | AC_PAR_AUDIO_WIDGET_CAP); | 590 | nid, AC_PAR_AUDIO_WIDGET_CAP); |
591 | return 0; | 591 | return 0; |
592 | } | 592 | } |
593 | 593 | ||
@@ -807,10 +807,6 @@ static void hda_jackpoll_work(struct work_struct *work) | |||
807 | codec->jackpoll_interval); | 807 | codec->jackpoll_interval); |
808 | } | 808 | } |
809 | 809 | ||
810 | static void init_hda_cache(struct hda_cache_rec *cache, | ||
811 | unsigned int record_size); | ||
812 | static void free_hda_cache(struct hda_cache_rec *cache); | ||
813 | |||
814 | /* release all pincfg lists */ | 810 | /* release all pincfg lists */ |
815 | static void free_init_pincfgs(struct hda_codec *codec) | 811 | static void free_init_pincfgs(struct hda_codec *codec) |
816 | { | 812 | { |
@@ -929,11 +925,6 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) | |||
929 | codec->proc_widget_hook = NULL; | 925 | codec->proc_widget_hook = NULL; |
930 | codec->spec = NULL; | 926 | codec->spec = NULL; |
931 | 927 | ||
932 | free_hda_cache(&codec->amp_cache); | ||
933 | 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)); | ||
936 | |||
937 | /* free only driver_pins so that init_pins + user_pins are restored */ | 928 | /* free only driver_pins so that init_pins + user_pins are restored */ |
938 | snd_array_free(&codec->driver_pins); | 929 | snd_array_free(&codec->driver_pins); |
939 | snd_array_free(&codec->cvt_setups); | 930 | snd_array_free(&codec->cvt_setups); |
@@ -945,6 +936,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) | |||
945 | snd_array_free(&codec->mixers); | 936 | snd_array_free(&codec->mixers); |
946 | snd_array_free(&codec->nids); | 937 | snd_array_free(&codec->nids); |
947 | remove_conn_list(codec); | 938 | remove_conn_list(codec); |
939 | snd_hdac_regmap_exit(&codec->core); | ||
948 | } | 940 | } |
949 | 941 | ||
950 | static unsigned int hda_set_power_state(struct hda_codec *codec, | 942 | static unsigned int hda_set_power_state(struct hda_codec *codec, |
@@ -995,8 +987,6 @@ static void snd_hda_codec_dev_release(struct device *dev) | |||
995 | free_init_pincfgs(codec); | 987 | free_init_pincfgs(codec); |
996 | snd_hdac_device_exit(&codec->core); | 988 | snd_hdac_device_exit(&codec->core); |
997 | snd_hda_sysfs_clear(codec); | 989 | snd_hda_sysfs_clear(codec); |
998 | free_hda_cache(&codec->amp_cache); | ||
999 | free_hda_cache(&codec->cmd_cache); | ||
1000 | kfree(codec->modelname); | 990 | kfree(codec->modelname); |
1001 | kfree(codec->wcaps); | 991 | kfree(codec->wcaps); |
1002 | kfree(codec); | 992 | kfree(codec); |
@@ -1049,9 +1039,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, | |||
1049 | codec->addr = codec_addr; | 1039 | codec->addr = codec_addr; |
1050 | mutex_init(&codec->spdif_mutex); | 1040 | mutex_init(&codec->spdif_mutex); |
1051 | mutex_init(&codec->control_mutex); | 1041 | mutex_init(&codec->control_mutex); |
1052 | mutex_init(&codec->hash_mutex); | ||
1053 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | ||
1054 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | ||
1055 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); | 1042 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1056 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | 1043 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); |
1057 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1044 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
@@ -1319,127 +1306,6 @@ static void hda_cleanup_all_streams(struct hda_codec *codec) | |||
1319 | * amp access functions | 1306 | * amp access functions |
1320 | */ | 1307 | */ |
1321 | 1308 | ||
1322 | /* FIXME: more better hash key? */ | ||
1323 | #define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | ||
1324 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | ||
1325 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) | ||
1326 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) | ||
1327 | #define INFO_AMP_CAPS (1<<0) | ||
1328 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | ||
1329 | |||
1330 | /* initialize the hash table */ | ||
1331 | static void init_hda_cache(struct hda_cache_rec *cache, | ||
1332 | unsigned int record_size) | ||
1333 | { | ||
1334 | memset(cache, 0, sizeof(*cache)); | ||
1335 | memset(cache->hash, 0xff, sizeof(cache->hash)); | ||
1336 | snd_array_init(&cache->buf, record_size, 64); | ||
1337 | } | ||
1338 | |||
1339 | static void free_hda_cache(struct hda_cache_rec *cache) | ||
1340 | { | ||
1341 | snd_array_free(&cache->buf); | ||
1342 | } | ||
1343 | |||
1344 | /* query the hash. allocate an entry if not found. */ | ||
1345 | static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) | ||
1346 | { | ||
1347 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | ||
1348 | u16 cur = cache->hash[idx]; | ||
1349 | struct hda_cache_head *info; | ||
1350 | |||
1351 | while (cur != 0xffff) { | ||
1352 | info = snd_array_elem(&cache->buf, cur); | ||
1353 | if (info->key == key) | ||
1354 | return info; | ||
1355 | cur = info->next; | ||
1356 | } | ||
1357 | return NULL; | ||
1358 | } | ||
1359 | |||
1360 | /* query the hash. allocate an entry if not found. */ | ||
1361 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | ||
1362 | u32 key) | ||
1363 | { | ||
1364 | struct hda_cache_head *info = get_hash(cache, key); | ||
1365 | if (!info) { | ||
1366 | u16 idx, cur; | ||
1367 | /* add a new hash entry */ | ||
1368 | info = snd_array_new(&cache->buf); | ||
1369 | if (!info) | ||
1370 | return NULL; | ||
1371 | cur = snd_array_index(&cache->buf, info); | ||
1372 | info->key = key; | ||
1373 | info->val = 0; | ||
1374 | info->dirty = 0; | ||
1375 | idx = key % (u16)ARRAY_SIZE(cache->hash); | ||
1376 | info->next = cache->hash[idx]; | ||
1377 | cache->hash[idx] = cur; | ||
1378 | } | ||
1379 | return info; | ||
1380 | } | ||
1381 | |||
1382 | /* query and allocate an amp hash entry */ | ||
1383 | static inline struct hda_amp_info * | ||
1384 | get_alloc_amp_hash(struct hda_codec *codec, u32 key) | ||
1385 | { | ||
1386 | return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); | ||
1387 | } | ||
1388 | |||
1389 | /* overwrite the value with the key in the caps hash */ | ||
1390 | static int write_caps_hash(struct hda_codec *codec, u32 key, unsigned int val) | ||
1391 | { | ||
1392 | struct hda_amp_info *info; | ||
1393 | |||
1394 | mutex_lock(&codec->hash_mutex); | ||
1395 | info = get_alloc_amp_hash(codec, key); | ||
1396 | if (!info) { | ||
1397 | mutex_unlock(&codec->hash_mutex); | ||
1398 | return -EINVAL; | ||
1399 | } | ||
1400 | info->amp_caps = val; | ||
1401 | info->head.val |= INFO_AMP_CAPS; | ||
1402 | mutex_unlock(&codec->hash_mutex); | ||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | /* query the value from the caps hash; if not found, fetch the current | ||
1407 | * value from the given function and store in the hash | ||
1408 | */ | ||
1409 | static unsigned int | ||
1410 | query_caps_hash(struct hda_codec *codec, hda_nid_t nid, int dir, u32 key, | ||
1411 | unsigned int (*func)(struct hda_codec *, hda_nid_t, int)) | ||
1412 | { | ||
1413 | struct hda_amp_info *info; | ||
1414 | unsigned int val; | ||
1415 | |||
1416 | mutex_lock(&codec->hash_mutex); | ||
1417 | info = get_alloc_amp_hash(codec, key); | ||
1418 | if (!info) { | ||
1419 | mutex_unlock(&codec->hash_mutex); | ||
1420 | return 0; | ||
1421 | } | ||
1422 | if (!(info->head.val & INFO_AMP_CAPS)) { | ||
1423 | mutex_unlock(&codec->hash_mutex); /* for reentrance */ | ||
1424 | val = func(codec, nid, dir); | ||
1425 | write_caps_hash(codec, key, val); | ||
1426 | } else { | ||
1427 | val = info->amp_caps; | ||
1428 | mutex_unlock(&codec->hash_mutex); | ||
1429 | } | ||
1430 | return val; | ||
1431 | } | ||
1432 | |||
1433 | static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid, | ||
1434 | int direction) | ||
1435 | { | ||
1436 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) | ||
1437 | nid = codec->core.afg; | ||
1438 | return snd_hda_param_read(codec, nid, | ||
1439 | direction == HDA_OUTPUT ? | ||
1440 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | ||
1441 | } | ||
1442 | |||
1443 | /** | 1309 | /** |
1444 | * query_amp_caps - query AMP capabilities | 1310 | * query_amp_caps - query AMP capabilities |
1445 | * @codec: the HD-auio codec | 1311 | * @codec: the HD-auio codec |
@@ -1454,9 +1320,11 @@ static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid, | |||
1454 | */ | 1320 | */ |
1455 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | 1321 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) |
1456 | { | 1322 | { |
1457 | return query_caps_hash(codec, nid, direction, | 1323 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) |
1458 | HDA_HASH_KEY(nid, direction, 0), | 1324 | nid = codec->core.afg; |
1459 | read_amp_cap); | 1325 | return snd_hda_param_read(codec, nid, |
1326 | direction == HDA_OUTPUT ? | ||
1327 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | ||
1460 | } | 1328 | } |
1461 | EXPORT_SYMBOL_GPL(query_amp_caps); | 1329 | EXPORT_SYMBOL_GPL(query_amp_caps); |
1462 | 1330 | ||
@@ -1497,183 +1365,14 @@ EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps); | |||
1497 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 1365 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
1498 | unsigned int caps) | 1366 | unsigned int caps) |
1499 | { | 1367 | { |
1500 | return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps); | 1368 | unsigned int parm; |
1501 | } | ||
1502 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); | ||
1503 | |||
1504 | static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid, | ||
1505 | int dir) | ||
1506 | { | ||
1507 | return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1508 | } | ||
1509 | |||
1510 | /** | ||
1511 | * snd_hda_query_pin_caps - Query PIN capabilities | ||
1512 | * @codec: the HD-auio codec | ||
1513 | * @nid: the NID to query | ||
1514 | * | ||
1515 | * Query PIN capabilities for the given widget. | ||
1516 | * Returns the obtained capability bits. | ||
1517 | * | ||
1518 | * When cap bits have been already read, this doesn't read again but | ||
1519 | * returns the cached value. | ||
1520 | */ | ||
1521 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
1522 | { | ||
1523 | return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid), | ||
1524 | read_pin_cap); | ||
1525 | } | ||
1526 | EXPORT_SYMBOL_GPL(snd_hda_query_pin_caps); | ||
1527 | |||
1528 | /** | ||
1529 | * snd_hda_override_pin_caps - Override the pin capabilities | ||
1530 | * @codec: the CODEC | ||
1531 | * @nid: the NID to override | ||
1532 | * @caps: the capability bits to set | ||
1533 | * | ||
1534 | * Override the cached PIN capabilitiy bits value by the given one. | ||
1535 | * | ||
1536 | * Returns zero if successful or a negative error code. | ||
1537 | */ | ||
1538 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | ||
1539 | unsigned int caps) | ||
1540 | { | ||
1541 | return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps); | ||
1542 | } | ||
1543 | EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps); | ||
1544 | |||
1545 | /* read or sync the hash value with the current value; | ||
1546 | * call within hash_mutex | ||
1547 | */ | ||
1548 | static struct hda_amp_info * | ||
1549 | update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
1550 | int direction, int index, bool init_only) | ||
1551 | { | ||
1552 | struct hda_amp_info *info; | ||
1553 | unsigned int parm, val = 0; | ||
1554 | bool val_read = false; | ||
1555 | |||
1556 | retry: | ||
1557 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); | ||
1558 | if (!info) | ||
1559 | return NULL; | ||
1560 | if (!(info->head.val & INFO_AMP_VOL(ch))) { | ||
1561 | if (!val_read) { | ||
1562 | mutex_unlock(&codec->hash_mutex); | ||
1563 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; | ||
1564 | parm |= direction == HDA_OUTPUT ? | ||
1565 | AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; | ||
1566 | parm |= index; | ||
1567 | val = snd_hda_codec_read(codec, nid, 0, | ||
1568 | AC_VERB_GET_AMP_GAIN_MUTE, parm); | ||
1569 | val &= 0xff; | ||
1570 | val_read = true; | ||
1571 | mutex_lock(&codec->hash_mutex); | ||
1572 | goto retry; | ||
1573 | } | ||
1574 | info->vol[ch] = val; | ||
1575 | info->head.val |= INFO_AMP_VOL(ch); | ||
1576 | } else if (init_only) | ||
1577 | return NULL; | ||
1578 | return info; | ||
1579 | } | ||
1580 | |||
1581 | /* | ||
1582 | * write the current volume in info to the h/w | ||
1583 | */ | ||
1584 | static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps, | ||
1585 | hda_nid_t nid, int ch, int direction, int index, | ||
1586 | int val) | ||
1587 | { | ||
1588 | u32 parm; | ||
1589 | |||
1590 | parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT; | ||
1591 | parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT; | ||
1592 | parm |= index << AC_AMP_SET_INDEX_SHIFT; | ||
1593 | if ((val & HDA_AMP_MUTE) && !(amp_caps & AC_AMPCAP_MUTE) && | ||
1594 | (amp_caps & AC_AMPCAP_MIN_MUTE)) | ||
1595 | ; /* set the zero value as a fake mute */ | ||
1596 | else | ||
1597 | parm |= val; | ||
1598 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); | ||
1599 | } | ||
1600 | |||
1601 | /** | ||
1602 | * snd_hda_codec_amp_read - Read AMP value | ||
1603 | * @codec: HD-audio codec | ||
1604 | * @nid: NID to read the AMP value | ||
1605 | * @ch: channel (left=0 or right=1) | ||
1606 | * @direction: #HDA_INPUT or #HDA_OUTPUT | ||
1607 | * @index: the index value (only for input direction) | ||
1608 | * | ||
1609 | * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. | ||
1610 | */ | ||
1611 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
1612 | int direction, int index) | ||
1613 | { | ||
1614 | struct hda_amp_info *info; | ||
1615 | unsigned int val = 0; | ||
1616 | |||
1617 | mutex_lock(&codec->hash_mutex); | ||
1618 | info = update_amp_hash(codec, nid, ch, direction, index, false); | ||
1619 | if (info) | ||
1620 | val = info->vol[ch]; | ||
1621 | mutex_unlock(&codec->hash_mutex); | ||
1622 | return val; | ||
1623 | } | ||
1624 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read); | ||
1625 | |||
1626 | static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
1627 | int direction, int idx, int mask, int val, | ||
1628 | bool init_only, bool cache_only) | ||
1629 | { | ||
1630 | struct hda_amp_info *info; | ||
1631 | unsigned int caps; | ||
1632 | |||
1633 | if (snd_BUG_ON(mask & ~0xff)) | ||
1634 | mask &= 0xff; | ||
1635 | val &= mask; | ||
1636 | |||
1637 | mutex_lock(&codec->hash_mutex); | ||
1638 | info = update_amp_hash(codec, nid, ch, direction, idx, init_only); | ||
1639 | if (!info) { | ||
1640 | mutex_unlock(&codec->hash_mutex); | ||
1641 | return 0; | ||
1642 | } | ||
1643 | val |= info->vol[ch] & ~mask; | ||
1644 | if (info->vol[ch] == val) { | ||
1645 | mutex_unlock(&codec->hash_mutex); | ||
1646 | return 0; | ||
1647 | } | ||
1648 | info->vol[ch] = val; | ||
1649 | info->head.dirty |= cache_only; | ||
1650 | caps = info->amp_caps; | ||
1651 | mutex_unlock(&codec->hash_mutex); | ||
1652 | if (!cache_only) | ||
1653 | put_vol_mute(codec, caps, nid, ch, direction, idx, val); | ||
1654 | return 1; | ||
1655 | } | ||
1656 | 1369 | ||
1657 | /** | 1370 | snd_hda_override_wcaps(codec, nid, |
1658 | * snd_hda_codec_amp_update - update the AMP value | 1371 | get_wcaps(codec, nid) | AC_WCAP_AMP_OVRD); |
1659 | * @codec: HD-audio codec | 1372 | parm = dir == HDA_OUTPUT ? AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP; |
1660 | * @nid: NID to read the AMP value | 1373 | return snd_hdac_override_parm(&codec->core, nid, parm, caps); |
1661 | * @ch: channel (left=0 or right=1) | ||
1662 | * @direction: #HDA_INPUT or #HDA_OUTPUT | ||
1663 | * @idx: the index value (only for input direction) | ||
1664 | * @mask: bit mask to set | ||
1665 | * @val: the bits value to set | ||
1666 | * | ||
1667 | * Update the AMP value with a bit mask. | ||
1668 | * Returns 0 if the value is unchanged, 1 if changed. | ||
1669 | */ | ||
1670 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
1671 | int direction, int idx, int mask, int val) | ||
1672 | { | ||
1673 | return codec_amp_update(codec, nid, ch, direction, idx, mask, val, | ||
1674 | false, codec->cached_write); | ||
1675 | } | 1374 | } |
1676 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update); | 1375 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); |
1677 | 1376 | ||
1678 | /** | 1377 | /** |
1679 | * snd_hda_codec_amp_stereo - update the AMP stereo values | 1378 | * snd_hda_codec_amp_stereo - update the AMP stereo values |
@@ -1718,8 +1417,16 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo); | |||
1718 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, | 1417 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, |
1719 | int dir, int idx, int mask, int val) | 1418 | int dir, int idx, int mask, int val) |
1720 | { | 1419 | { |
1721 | return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true, | 1420 | int orig; |
1722 | codec->cached_write); | 1421 | |
1422 | if (!codec->core.regmap) | ||
1423 | return -EINVAL; | ||
1424 | regcache_cache_only(codec->core.regmap, true); | ||
1425 | orig = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); | ||
1426 | regcache_cache_only(codec->core.regmap, false); | ||
1427 | if (orig >= 0) | ||
1428 | return 0; | ||
1429 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val); | ||
1723 | } | 1430 | } |
1724 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init); | 1431 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init); |
1725 | 1432 | ||
@@ -1748,49 +1455,6 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
1748 | } | 1455 | } |
1749 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo); | 1456 | EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo); |
1750 | 1457 | ||
1751 | /** | ||
1752 | * snd_hda_codec_resume_amp - Resume all AMP commands from the cache | ||
1753 | * @codec: HD-audio codec | ||
1754 | * | ||
1755 | * Resume the all amp commands from the cache. | ||
1756 | */ | ||
1757 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | ||
1758 | { | ||
1759 | int i; | ||
1760 | |||
1761 | mutex_lock(&codec->hash_mutex); | ||
1762 | codec->cached_write = 0; | ||
1763 | for (i = 0; i < codec->amp_cache.buf.used; i++) { | ||
1764 | struct hda_amp_info *buffer; | ||
1765 | u32 key; | ||
1766 | hda_nid_t nid; | ||
1767 | unsigned int idx, dir, ch; | ||
1768 | struct hda_amp_info info; | ||
1769 | |||
1770 | buffer = snd_array_elem(&codec->amp_cache.buf, i); | ||
1771 | if (!buffer->head.dirty) | ||
1772 | continue; | ||
1773 | buffer->head.dirty = 0; | ||
1774 | info = *buffer; | ||
1775 | key = info.head.key; | ||
1776 | if (!key) | ||
1777 | continue; | ||
1778 | nid = key & 0xff; | ||
1779 | idx = (key >> 16) & 0xff; | ||
1780 | dir = (key >> 24) & 0xff; | ||
1781 | for (ch = 0; ch < 2; ch++) { | ||
1782 | if (!(info.head.val & INFO_AMP_VOL(ch))) | ||
1783 | continue; | ||
1784 | mutex_unlock(&codec->hash_mutex); | ||
1785 | put_vol_mute(codec, info.amp_caps, nid, ch, dir, idx, | ||
1786 | info.vol[ch]); | ||
1787 | mutex_lock(&codec->hash_mutex); | ||
1788 | } | ||
1789 | } | ||
1790 | mutex_unlock(&codec->hash_mutex); | ||
1791 | } | ||
1792 | EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp); | ||
1793 | |||
1794 | static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, | 1458 | static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, |
1795 | unsigned int ofs) | 1459 | unsigned int ofs) |
1796 | { | 1460 | { |
@@ -1861,8 +1525,8 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid, | |||
1861 | maxval = get_amp_max_value(codec, nid, dir, 0); | 1525 | maxval = get_amp_max_value(codec, nid, dir, 0); |
1862 | if (val > maxval) | 1526 | if (val > maxval) |
1863 | val = maxval; | 1527 | val = maxval; |
1864 | return codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val, | 1528 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, |
1865 | false, !hda_codec_is_power_on(codec)); | 1529 | HDA_AMP_VOLMASK, val); |
1866 | } | 1530 | } |
1867 | 1531 | ||
1868 | /** | 1532 | /** |
@@ -2545,17 +2209,15 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2545 | int change = 0; | 2209 | int change = 0; |
2546 | 2210 | ||
2547 | if (chs & 1) { | 2211 | if (chs & 1) { |
2548 | change = codec_amp_update(codec, nid, 0, dir, idx, | 2212 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
2549 | HDA_AMP_MUTE, | 2213 | HDA_AMP_MUTE, |
2550 | *valp ? 0 : HDA_AMP_MUTE, false, | 2214 | *valp ? 0 : HDA_AMP_MUTE); |
2551 | !hda_codec_is_power_on(codec)); | ||
2552 | valp++; | 2215 | valp++; |
2553 | } | 2216 | } |
2554 | if (chs & 2) | 2217 | if (chs & 2) |
2555 | change |= codec_amp_update(codec, nid, 1, dir, idx, | 2218 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
2556 | HDA_AMP_MUTE, | 2219 | HDA_AMP_MUTE, |
2557 | *valp ? 0 : HDA_AMP_MUTE, false, | 2220 | *valp ? 0 : HDA_AMP_MUTE); |
2558 | !hda_codec_is_power_on(codec)); | ||
2559 | hda_call_check_power_status(codec, nid); | 2221 | hda_call_check_power_status(codec, nid); |
2560 | return change; | 2222 | return change; |
2561 | } | 2223 | } |
@@ -2857,25 +2519,35 @@ static unsigned int convert_to_spdif_status(unsigned short val) | |||
2857 | 2519 | ||
2858 | /* set digital convert verbs both for the given NID and its slaves */ | 2520 | /* set digital convert verbs both for the given NID and its slaves */ |
2859 | static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, | 2521 | static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, |
2860 | int verb, int val) | 2522 | int mask, int val) |
2861 | { | 2523 | { |
2862 | const hda_nid_t *d; | 2524 | const hda_nid_t *d; |
2863 | 2525 | ||
2864 | snd_hda_codec_write_cache(codec, nid, 0, verb, val); | 2526 | snd_hdac_regmap_update(&codec->core, nid, AC_VERB_SET_DIGI_CONVERT_1, |
2527 | mask, val); | ||
2865 | d = codec->slave_dig_outs; | 2528 | d = codec->slave_dig_outs; |
2866 | if (!d) | 2529 | if (!d) |
2867 | return; | 2530 | return; |
2868 | for (; *d; d++) | 2531 | for (; *d; d++) |
2869 | snd_hda_codec_write_cache(codec, *d, 0, verb, val); | 2532 | snd_hdac_regmap_update(&codec->core, nid, |
2533 | AC_VERB_SET_DIGI_CONVERT_1, mask, val); | ||
2870 | } | 2534 | } |
2871 | 2535 | ||
2872 | static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid, | 2536 | static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid, |
2873 | int dig1, int dig2) | 2537 | int dig1, int dig2) |
2874 | { | 2538 | { |
2875 | if (dig1 != -1) | 2539 | unsigned int mask = 0; |
2876 | set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1); | 2540 | unsigned int val = 0; |
2877 | if (dig2 != -1) | 2541 | |
2878 | set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2); | 2542 | if (dig1 != -1) { |
2543 | mask |= 0xff; | ||
2544 | val = dig1; | ||
2545 | } | ||
2546 | if (dig2 != -1) { | ||
2547 | mask |= 0xff00; | ||
2548 | val |= dig2 << 8; | ||
2549 | } | ||
2550 | set_dig_out(codec, nid, mask, val); | ||
2879 | } | 2551 | } |
2880 | 2552 | ||
2881 | static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, | 2553 | static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, |
@@ -3008,6 +2680,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec, | |||
3008 | struct snd_kcontrol *kctl; | 2680 | struct snd_kcontrol *kctl; |
3009 | struct snd_kcontrol_new *dig_mix; | 2681 | struct snd_kcontrol_new *dig_mix; |
3010 | int idx = 0; | 2682 | int idx = 0; |
2683 | int val = 0; | ||
3011 | const int spdif_index = 16; | 2684 | const int spdif_index = 16; |
3012 | struct hda_spdif_out *spdif; | 2685 | struct hda_spdif_out *spdif; |
3013 | struct hda_bus *bus = codec->bus; | 2686 | struct hda_bus *bus = codec->bus; |
@@ -3048,8 +2721,9 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec, | |||
3048 | return err; | 2721 | return err; |
3049 | } | 2722 | } |
3050 | spdif->nid = cvt_nid; | 2723 | spdif->nid = cvt_nid; |
3051 | spdif->ctls = snd_hda_codec_read(codec, cvt_nid, 0, | 2724 | snd_hdac_regmap_read(&codec->core, cvt_nid, |
3052 | AC_VERB_GET_DIGI_CONVERT_1, 0); | 2725 | AC_VERB_GET_DIGI_CONVERT_1, &val); |
2726 | spdif->ctls = val; | ||
3053 | spdif->status = convert_to_spdif_status(spdif->ctls); | 2727 | spdif->status = convert_to_spdif_status(spdif->ctls); |
3054 | return 0; | 2728 | return 0; |
3055 | } | 2729 | } |
@@ -3193,8 +2867,8 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, | |||
3193 | change = codec->spdif_in_enable != val; | 2867 | change = codec->spdif_in_enable != val; |
3194 | if (change) { | 2868 | if (change) { |
3195 | codec->spdif_in_enable = val; | 2869 | codec->spdif_in_enable = val; |
3196 | snd_hda_codec_write_cache(codec, nid, 0, | 2870 | snd_hdac_regmap_write(&codec->core, nid, |
3197 | AC_VERB_SET_DIGI_CONVERT_1, val); | 2871 | AC_VERB_SET_DIGI_CONVERT_1, val); |
3198 | } | 2872 | } |
3199 | mutex_unlock(&codec->spdif_mutex); | 2873 | mutex_unlock(&codec->spdif_mutex); |
3200 | return change; | 2874 | return change; |
@@ -3205,10 +2879,11 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, | |||
3205 | { | 2879 | { |
3206 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2880 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3207 | hda_nid_t nid = kcontrol->private_value; | 2881 | hda_nid_t nid = kcontrol->private_value; |
3208 | unsigned short val; | 2882 | unsigned int val; |
3209 | unsigned int sbits; | 2883 | unsigned int sbits; |
3210 | 2884 | ||
3211 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0); | 2885 | snd_hdac_regmap_read(&codec->core, nid, |
2886 | AC_VERB_GET_DIGI_CONVERT_1, &val); | ||
3212 | sbits = convert_to_spdif_status(val); | 2887 | sbits = convert_to_spdif_status(val); |
3213 | ucontrol->value.iec958.status[0] = sbits; | 2888 | ucontrol->value.iec958.status[0] = sbits; |
3214 | ucontrol->value.iec958.status[1] = sbits >> 8; | 2889 | ucontrol->value.iec958.status[1] = sbits >> 8; |
@@ -3274,153 +2949,6 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
3274 | } | 2949 | } |
3275 | EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls); | 2950 | EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls); |
3276 | 2951 | ||
3277 | /* | ||
3278 | * command cache | ||
3279 | */ | ||
3280 | |||
3281 | /* build a 31bit cache key with the widget id and the command parameter */ | ||
3282 | #define build_cmd_cache_key(nid, verb) ((verb << 8) | nid) | ||
3283 | #define get_cmd_cache_nid(key) ((key) & 0xff) | ||
3284 | #define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff) | ||
3285 | |||
3286 | /** | ||
3287 | * snd_hda_codec_write_cache - send a single command with caching | ||
3288 | * @codec: the HDA codec | ||
3289 | * @nid: NID to send the command | ||
3290 | * @flags: optional bit flags | ||
3291 | * @verb: the verb to send | ||
3292 | * @parm: the parameter for the verb | ||
3293 | * | ||
3294 | * Send a single command without waiting for response. | ||
3295 | * | ||
3296 | * Returns 0 if successful, or a negative error code. | ||
3297 | */ | ||
3298 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | ||
3299 | int flags, unsigned int verb, unsigned int parm) | ||
3300 | { | ||
3301 | int err; | ||
3302 | struct hda_cache_head *c; | ||
3303 | u32 key; | ||
3304 | unsigned int cache_only; | ||
3305 | |||
3306 | cache_only = codec->cached_write; | ||
3307 | if (!cache_only) { | ||
3308 | err = snd_hda_codec_write(codec, nid, flags, verb, parm); | ||
3309 | if (err < 0) | ||
3310 | return err; | ||
3311 | } | ||
3312 | |||
3313 | /* parm may contain the verb stuff for get/set amp */ | ||
3314 | verb = verb | (parm >> 8); | ||
3315 | parm &= 0xff; | ||
3316 | key = build_cmd_cache_key(nid, verb); | ||
3317 | mutex_lock(&codec->bus->core.cmd_mutex); | ||
3318 | c = get_alloc_hash(&codec->cmd_cache, key); | ||
3319 | if (c) { | ||
3320 | c->val = parm; | ||
3321 | c->dirty = cache_only; | ||
3322 | } | ||
3323 | mutex_unlock(&codec->bus->core.cmd_mutex); | ||
3324 | return 0; | ||
3325 | } | ||
3326 | EXPORT_SYMBOL_GPL(snd_hda_codec_write_cache); | ||
3327 | |||
3328 | /** | ||
3329 | * snd_hda_codec_update_cache - check cache and write the cmd only when needed | ||
3330 | * @codec: the HDA codec | ||
3331 | * @nid: NID to send the command | ||
3332 | * @flags: optional bit flags | ||
3333 | * @verb: the verb to send | ||
3334 | * @parm: the parameter for the verb | ||
3335 | * | ||
3336 | * This function works like snd_hda_codec_write_cache(), but it doesn't send | ||
3337 | * command if the parameter is already identical with the cached value. | ||
3338 | * If not, it sends the command and refreshes the cache. | ||
3339 | * | ||
3340 | * Returns 0 if successful, or a negative error code. | ||
3341 | */ | ||
3342 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | ||
3343 | int flags, unsigned int verb, unsigned int parm) | ||
3344 | { | ||
3345 | struct hda_cache_head *c; | ||
3346 | u32 key; | ||
3347 | |||
3348 | /* parm may contain the verb stuff for get/set amp */ | ||
3349 | verb = verb | (parm >> 8); | ||
3350 | parm &= 0xff; | ||
3351 | key = build_cmd_cache_key(nid, verb); | ||
3352 | mutex_lock(&codec->bus->core.cmd_mutex); | ||
3353 | c = get_hash(&codec->cmd_cache, key); | ||
3354 | if (c && c->val == parm) { | ||
3355 | mutex_unlock(&codec->bus->core.cmd_mutex); | ||
3356 | return 0; | ||
3357 | } | ||
3358 | mutex_unlock(&codec->bus->core.cmd_mutex); | ||
3359 | return snd_hda_codec_write_cache(codec, nid, flags, verb, parm); | ||
3360 | } | ||
3361 | EXPORT_SYMBOL_GPL(snd_hda_codec_update_cache); | ||
3362 | |||
3363 | /** | ||
3364 | * snd_hda_codec_resume_cache - Resume the all commands from the cache | ||
3365 | * @codec: HD-audio codec | ||
3366 | * | ||
3367 | * Execute all verbs recorded in the command caches to resume. | ||
3368 | */ | ||
3369 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | ||
3370 | { | ||
3371 | int i; | ||
3372 | |||
3373 | mutex_lock(&codec->hash_mutex); | ||
3374 | codec->cached_write = 0; | ||
3375 | for (i = 0; i < codec->cmd_cache.buf.used; i++) { | ||
3376 | struct hda_cache_head *buffer; | ||
3377 | u32 key; | ||
3378 | |||
3379 | buffer = snd_array_elem(&codec->cmd_cache.buf, i); | ||
3380 | key = buffer->key; | ||
3381 | if (!key) | ||
3382 | continue; | ||
3383 | if (!buffer->dirty) | ||
3384 | continue; | ||
3385 | buffer->dirty = 0; | ||
3386 | mutex_unlock(&codec->hash_mutex); | ||
3387 | snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0, | ||
3388 | get_cmd_cache_cmd(key), buffer->val); | ||
3389 | mutex_lock(&codec->hash_mutex); | ||
3390 | } | ||
3391 | mutex_unlock(&codec->hash_mutex); | ||
3392 | } | ||
3393 | EXPORT_SYMBOL_GPL(snd_hda_codec_resume_cache); | ||
3394 | |||
3395 | /** | ||
3396 | * snd_hda_sequence_write_cache - sequence writes with caching | ||
3397 | * @codec: the HDA codec | ||
3398 | * @seq: VERB array to send | ||
3399 | * | ||
3400 | * Send the commands sequentially from the given array. | ||
3401 | * Thte commands are recorded on cache for power-save and resume. | ||
3402 | * The array must be terminated with NID=0. | ||
3403 | */ | ||
3404 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | ||
3405 | const struct hda_verb *seq) | ||
3406 | { | ||
3407 | for (; seq->nid; seq++) | ||
3408 | snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, | ||
3409 | seq->param); | ||
3410 | } | ||
3411 | EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache); | ||
3412 | |||
3413 | /** | ||
3414 | * snd_hda_codec_flush_cache - Execute all pending (cached) amps / verbs | ||
3415 | * @codec: HD-audio codec | ||
3416 | */ | ||
3417 | void snd_hda_codec_flush_cache(struct hda_codec *codec) | ||
3418 | { | ||
3419 | snd_hda_codec_resume_amp(codec); | ||
3420 | snd_hda_codec_resume_cache(codec); | ||
3421 | } | ||
3422 | EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache); | ||
3423 | |||
3424 | /** | 2952 | /** |
3425 | * snd_hda_codec_set_power_to_all - Set the power state to all widgets | 2953 | * snd_hda_codec_set_power_to_all - Set the power state to all widgets |
3426 | * @codec: the HDA codec | 2954 | * @codec: the HDA codec |
@@ -3621,22 +3149,6 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec) | |||
3621 | return state; | 3149 | return state; |
3622 | } | 3150 | } |
3623 | 3151 | ||
3624 | /* mark all entries of cmd and amp caches dirty */ | ||
3625 | static void hda_mark_cmd_cache_dirty(struct hda_codec *codec) | ||
3626 | { | ||
3627 | int i; | ||
3628 | for (i = 0; i < codec->cmd_cache.buf.used; i++) { | ||
3629 | struct hda_cache_head *cmd; | ||
3630 | cmd = snd_array_elem(&codec->cmd_cache.buf, i); | ||
3631 | cmd->dirty = 1; | ||
3632 | } | ||
3633 | for (i = 0; i < codec->amp_cache.buf.used; i++) { | ||
3634 | struct hda_amp_info *amp; | ||
3635 | amp = snd_array_elem(&codec->amp_cache.buf, i); | ||
3636 | amp->head.dirty = 1; | ||
3637 | } | ||
3638 | } | ||
3639 | |||
3640 | /* | 3152 | /* |
3641 | * kick up codec; used both from PM and power-save | 3153 | * kick up codec; used both from PM and power-save |
3642 | */ | 3154 | */ |
@@ -3644,7 +3156,8 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
3644 | { | 3156 | { |
3645 | atomic_inc(&codec->core.in_pm); | 3157 | atomic_inc(&codec->core.in_pm); |
3646 | 3158 | ||
3647 | hda_mark_cmd_cache_dirty(codec); | 3159 | if (codec->core.regmap) |
3160 | regcache_mark_dirty(codec->core.regmap); | ||
3648 | 3161 | ||
3649 | codec->power_jiffies = jiffies; | 3162 | codec->power_jiffies = jiffies; |
3650 | 3163 | ||
@@ -3657,8 +3170,8 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
3657 | else { | 3170 | else { |
3658 | if (codec->patch_ops.init) | 3171 | if (codec->patch_ops.init) |
3659 | codec->patch_ops.init(codec); | 3172 | codec->patch_ops.init(codec); |
3660 | snd_hda_codec_resume_amp(codec); | 3173 | if (codec->core.regmap) |
3661 | snd_hda_codec_resume_cache(codec); | 3174 | regcache_sync(codec->core.regmap); |
3662 | } | 3175 | } |
3663 | 3176 | ||
3664 | if (codec->jackpoll_interval) | 3177 | if (codec->jackpoll_interval) |
@@ -3878,8 +3391,7 @@ unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, | |||
3878 | } | 3391 | } |
3879 | EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); | 3392 | EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); |
3880 | 3393 | ||
3881 | static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid, | 3394 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) |
3882 | int dir) | ||
3883 | { | 3395 | { |
3884 | unsigned int val = 0; | 3396 | unsigned int val = 0; |
3885 | if (nid != codec->core.afg && | 3397 | if (nid != codec->core.afg && |
@@ -3892,14 +3404,7 @@ static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid, | |||
3892 | return val; | 3404 | return val; |
3893 | } | 3405 | } |
3894 | 3406 | ||
3895 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) | 3407 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) |
3896 | { | ||
3897 | return query_caps_hash(codec, nid, 0, HDA_HASH_PARPCM_KEY(nid), | ||
3898 | get_pcm_param); | ||
3899 | } | ||
3900 | |||
3901 | static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid, | ||
3902 | int dir) | ||
3903 | { | 3408 | { |
3904 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 3409 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
3905 | if (!streams || streams == -1) | 3410 | if (!streams || streams == -1) |
@@ -3909,12 +3414,6 @@ static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid, | |||
3909 | return streams; | 3414 | return streams; |
3910 | } | 3415 | } |
3911 | 3416 | ||
3912 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) | ||
3913 | { | ||
3914 | return query_caps_hash(codec, nid, 0, HDA_HASH_PARSTR_KEY(nid), | ||
3915 | get_stream_param); | ||
3916 | } | ||
3917 | |||
3918 | /** | 3417 | /** |
3919 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | 3418 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats |
3920 | * @codec: the HDA codec | 3419 | * @codec: the HDA codec |
@@ -5012,52 +4511,6 @@ void snd_hda_bus_reset(struct hda_bus *bus) | |||
5012 | } | 4511 | } |
5013 | EXPORT_SYMBOL_GPL(snd_hda_bus_reset); | 4512 | EXPORT_SYMBOL_GPL(snd_hda_bus_reset); |
5014 | 4513 | ||
5015 | /* | ||
5016 | * generic arrays | ||
5017 | */ | ||
5018 | |||
5019 | /** | ||
5020 | * snd_array_new - get a new element from the given array | ||
5021 | * @array: the array object | ||
5022 | * | ||
5023 | * Get a new element from the given array. If it exceeds the | ||
5024 | * pre-allocated array size, re-allocate the array. | ||
5025 | * | ||
5026 | * Returns NULL if allocation failed. | ||
5027 | */ | ||
5028 | void *snd_array_new(struct snd_array *array) | ||
5029 | { | ||
5030 | if (snd_BUG_ON(!array->elem_size)) | ||
5031 | return NULL; | ||
5032 | if (array->used >= array->alloced) { | ||
5033 | int num = array->alloced + array->alloc_align; | ||
5034 | int size = (num + 1) * array->elem_size; | ||
5035 | void *nlist; | ||
5036 | if (snd_BUG_ON(num >= 4096)) | ||
5037 | return NULL; | ||
5038 | nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO); | ||
5039 | if (!nlist) | ||
5040 | return NULL; | ||
5041 | array->list = nlist; | ||
5042 | array->alloced = num; | ||
5043 | } | ||
5044 | return snd_array_elem(array, array->used++); | ||
5045 | } | ||
5046 | EXPORT_SYMBOL_GPL(snd_array_new); | ||
5047 | |||
5048 | /** | ||
5049 | * snd_array_free - free the given array elements | ||
5050 | * @array: the array object | ||
5051 | */ | ||
5052 | void snd_array_free(struct snd_array *array) | ||
5053 | { | ||
5054 | kfree(array->list); | ||
5055 | array->used = 0; | ||
5056 | array->alloced = 0; | ||
5057 | array->list = NULL; | ||
5058 | } | ||
5059 | EXPORT_SYMBOL_GPL(snd_array_free); | ||
5060 | |||
5061 | /** | 4514 | /** |
5062 | * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer | 4515 | * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer |
5063 | * @pcm: PCM caps bits | 4516 | * @pcm: PCM caps bits |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 21632174744b..acf868c6a785 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -28,36 +28,7 @@ | |||
28 | #include <sound/hwdep.h> | 28 | #include <sound/hwdep.h> |
29 | #include <sound/hdaudio.h> | 29 | #include <sound/hdaudio.h> |
30 | #include <sound/hda_verbs.h> | 30 | #include <sound/hda_verbs.h> |
31 | 31 | #include <sound/hda_regmap.h> | |
32 | /* | ||
33 | * generic arrays | ||
34 | */ | ||
35 | struct snd_array { | ||
36 | unsigned int used; | ||
37 | unsigned int alloced; | ||
38 | unsigned int elem_size; | ||
39 | unsigned int alloc_align; | ||
40 | void *list; | ||
41 | }; | ||
42 | |||
43 | void *snd_array_new(struct snd_array *array); | ||
44 | void snd_array_free(struct snd_array *array); | ||
45 | static inline void snd_array_init(struct snd_array *array, unsigned int size, | ||
46 | unsigned int align) | ||
47 | { | ||
48 | array->elem_size = size; | ||
49 | array->alloc_align = align; | ||
50 | } | ||
51 | |||
52 | static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) | ||
53 | { | ||
54 | return array->list + idx * array->elem_size; | ||
55 | } | ||
56 | |||
57 | static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) | ||
58 | { | ||
59 | return (unsigned long)(ptr - array->list) / array->elem_size; | ||
60 | } | ||
61 | 32 | ||
62 | /* | 33 | /* |
63 | * Structures | 34 | * Structures |
@@ -181,25 +152,6 @@ struct hda_codec_ops { | |||
181 | void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on); | 152 | void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on); |
182 | }; | 153 | }; |
183 | 154 | ||
184 | /* record for amp information cache */ | ||
185 | struct hda_cache_head { | ||
186 | u32 key:31; /* hash key */ | ||
187 | u32 dirty:1; | ||
188 | u16 val; /* assigned value */ | ||
189 | u16 next; | ||
190 | }; | ||
191 | |||
192 | struct hda_amp_info { | ||
193 | struct hda_cache_head head; | ||
194 | u32 amp_caps; /* amp capabilities */ | ||
195 | u16 vol[2]; /* current volume & mute */ | ||
196 | }; | ||
197 | |||
198 | struct hda_cache_rec { | ||
199 | u16 hash[64]; /* hash table for index */ | ||
200 | struct snd_array buf; /* record entries */ | ||
201 | }; | ||
202 | |||
203 | /* PCM callbacks */ | 155 | /* PCM callbacks */ |
204 | struct hda_pcm_ops { | 156 | struct hda_pcm_ops { |
205 | int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec, | 157 | int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec, |
@@ -283,14 +235,10 @@ struct hda_codec { | |||
283 | struct snd_array mixers; /* list of assigned mixer elements */ | 235 | struct snd_array mixers; /* list of assigned mixer elements */ |
284 | struct snd_array nids; /* list of mapped mixer elements */ | 236 | struct snd_array nids; /* list of mapped mixer elements */ |
285 | 237 | ||
286 | struct hda_cache_rec amp_cache; /* cache for amp access */ | ||
287 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | ||
288 | |||
289 | struct list_head conn_list; /* linked-list of connection-list */ | 238 | struct list_head conn_list; /* linked-list of connection-list */ |
290 | 239 | ||
291 | struct mutex spdif_mutex; | 240 | struct mutex spdif_mutex; |
292 | struct mutex control_mutex; | 241 | struct mutex control_mutex; |
293 | struct mutex hash_mutex; | ||
294 | struct snd_array spdif_out; | 242 | struct snd_array spdif_out; |
295 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 243 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
296 | const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 244 | const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
@@ -395,7 +343,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
395 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, | 343 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, |
396 | unsigned int verb, unsigned int parm); | 344 | unsigned int verb, unsigned int parm); |
397 | #define snd_hda_param_read(codec, nid, param) \ | 345 | #define snd_hda_param_read(codec, nid, param) \ |
398 | snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) | 346 | snd_hdac_read_parm(&(codec)->core, nid, param) |
399 | #define snd_hda_get_sub_nodes(codec, nid, start_nid) \ | 347 | #define snd_hda_get_sub_nodes(codec, nid, start_nid) \ |
400 | snd_hdac_get_sub_nodes(&(codec)->core, nid, start_nid) | 348 | snd_hdac_get_sub_nodes(&(codec)->core, nid, start_nid) |
401 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | 349 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, |
@@ -439,15 +387,15 @@ snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) | |||
439 | } | 387 | } |
440 | 388 | ||
441 | /* cached write */ | 389 | /* cached write */ |
442 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 390 | static inline int |
443 | int flags, unsigned int verb, unsigned int parm); | 391 | snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
444 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 392 | int flags, unsigned int verb, unsigned int parm) |
445 | const struct hda_verb *seq); | 393 | { |
446 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | 394 | return snd_hdac_regmap_write(&codec->core, nid, verb, parm); |
447 | int flags, unsigned int verb, unsigned int parm); | 395 | } |
448 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | 396 | |
449 | /* both for cmd & amp caches */ | 397 | #define snd_hda_codec_update_cache(codec, nid, flags, verb, parm) \ |
450 | void snd_hda_codec_flush_cache(struct hda_codec *codec); | 398 | snd_hda_codec_write_cache(codec, nid, flags, verb, parm) |
451 | 399 | ||
452 | /* the struct for codec->pin_configs */ | 400 | /* the struct for codec->pin_configs */ |
453 | struct hda_pincfg { | 401 | struct hda_pincfg { |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 4850f92c89c4..f7ccef5559de 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -3381,11 +3381,6 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, | |||
3381 | imux = &spec->input_mux; | 3381 | imux = &spec->input_mux; |
3382 | adc_idx = kcontrol->id.index; | 3382 | adc_idx = kcontrol->id.index; |
3383 | mutex_lock(&codec->control_mutex); | 3383 | mutex_lock(&codec->control_mutex); |
3384 | /* we use the cache-only update at first since multiple input paths | ||
3385 | * may shared the same amp; by updating only caches, the redundant | ||
3386 | * writes to hardware can be reduced. | ||
3387 | */ | ||
3388 | codec->cached_write = 1; | ||
3389 | for (i = 0; i < imux->num_items; i++) { | 3384 | for (i = 0; i < imux->num_items; i++) { |
3390 | path = get_input_path(codec, adc_idx, i); | 3385 | path = get_input_path(codec, adc_idx, i); |
3391 | if (!path || !path->ctls[type]) | 3386 | if (!path || !path->ctls[type]) |
@@ -3393,12 +3388,9 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, | |||
3393 | kcontrol->private_value = path->ctls[type]; | 3388 | kcontrol->private_value = path->ctls[type]; |
3394 | err = func(kcontrol, ucontrol); | 3389 | err = func(kcontrol, ucontrol); |
3395 | if (err < 0) | 3390 | if (err < 0) |
3396 | goto error; | 3391 | break; |
3397 | } | 3392 | } |
3398 | error: | ||
3399 | codec->cached_write = 0; | ||
3400 | mutex_unlock(&codec->control_mutex); | 3393 | mutex_unlock(&codec->control_mutex); |
3401 | snd_hda_codec_flush_cache(codec); /* flush the updates */ | ||
3402 | if (err >= 0 && spec->cap_sync_hook) | 3394 | if (err >= 0 && spec->cap_sync_hook) |
3403 | spec->cap_sync_hook(codec, kcontrol, ucontrol); | 3395 | spec->cap_sync_hook(codec, kcontrol, ucontrol); |
3404 | return err; | 3396 | return err; |
@@ -5760,8 +5752,6 @@ int snd_hda_gen_init(struct hda_codec *codec) | |||
5760 | 5752 | ||
5761 | snd_hda_apply_verbs(codec); | 5753 | snd_hda_apply_verbs(codec); |
5762 | 5754 | ||
5763 | codec->cached_write = 1; | ||
5764 | |||
5765 | init_multi_out(codec); | 5755 | init_multi_out(codec); |
5766 | init_extra_out(codec); | 5756 | init_extra_out(codec); |
5767 | init_multi_io(codec); | 5757 | init_multi_io(codec); |
@@ -5777,7 +5767,7 @@ int snd_hda_gen_init(struct hda_codec *codec) | |||
5777 | /* call init functions of standard auto-mute helpers */ | 5767 | /* call init functions of standard auto-mute helpers */ |
5778 | update_automute_all(codec); | 5768 | update_automute_all(codec); |
5779 | 5769 | ||
5780 | snd_hda_codec_flush_cache(codec); | 5770 | regcache_sync(codec->core.regmap); |
5781 | 5771 | ||
5782 | if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook) | 5772 | if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook) |
5783 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | 5773 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 8a83775e0e27..3b567f42296b 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -127,18 +127,16 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | |||
127 | struct snd_ctl_elem_value *ucontrol); | 127 | struct snd_ctl_elem_value *ucontrol); |
128 | #endif | 128 | #endif |
129 | /* lowlevel accessor with caching; use carefully */ | 129 | /* lowlevel accessor with caching; use carefully */ |
130 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | 130 | #define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \ |
131 | int direction, int index); | 131 | snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx) |
132 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | 132 | #define snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val) \ |
133 | int direction, int idx, int mask, int val); | 133 | snd_hdac_regmap_update_amp(&(codec)->core, nid, ch, dir, idx, mask, val) |
134 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 134 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, |
135 | int dir, int idx, int mask, int val); | 135 | int dir, int idx, int mask, int val); |
136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, | 136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, |
137 | int direction, int idx, int mask, int val); | 137 | int direction, int idx, int mask, int val); |
138 | int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid, | 138 | int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid, |
139 | int dir, int idx, int mask, int val); | 139 | int dir, int idx, int mask, int val); |
140 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | ||
141 | |||
142 | void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | 140 | void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, |
143 | unsigned int *tlv); | 141 | unsigned int *tlv); |
144 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 142 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, |
@@ -559,9 +557,41 @@ static inline void snd_hda_override_wcaps(struct hda_codec *codec, | |||
559 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | 557 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); |
560 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 558 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
561 | unsigned int caps); | 559 | unsigned int caps); |
562 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | 560 | /** |
563 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | 561 | * snd_hda_query_pin_caps - Query PIN capabilities |
564 | unsigned int caps); | 562 | * @codec: the HD-auio codec |
563 | * @nid: the NID to query | ||
564 | * | ||
565 | * Query PIN capabilities for the given widget. | ||
566 | * Returns the obtained capability bits. | ||
567 | * | ||
568 | * When cap bits have been already read, this doesn't read again but | ||
569 | * returns the cached value. | ||
570 | */ | ||
571 | static inline u32 | ||
572 | snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
573 | { | ||
574 | return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
575 | |||
576 | } | ||
577 | |||
578 | /** | ||
579 | * snd_hda_override_pin_caps - Override the pin capabilities | ||
580 | * @codec: the CODEC | ||
581 | * @nid: the NID to override | ||
582 | * @caps: the capability bits to set | ||
583 | * | ||
584 | * Override the cached PIN capabilitiy bits value by the given one. | ||
585 | * | ||
586 | * Returns zero if successful or a negative error code. | ||
587 | */ | ||
588 | static inline int | ||
589 | snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | ||
590 | unsigned int caps) | ||
591 | { | ||
592 | return snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP, caps); | ||
593 | } | ||
594 | |||
565 | bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | 595 | bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid, |
566 | int dir, unsigned int bits); | 596 | int dir, unsigned int bits); |
567 | 597 | ||
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index a4f5a30f1d41..ee6230767c64 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -32,6 +32,10 @@ static int dump_coef = -1; | |||
32 | module_param(dump_coef, int, 0644); | 32 | module_param(dump_coef, int, 0644); |
33 | MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)"); | 33 | MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)"); |
34 | 34 | ||
35 | /* always use noncached version */ | ||
36 | #define param_read(codec, nid, parm) \ | ||
37 | snd_hdac_read_parm_uncached(&(codec)->core, nid, parm) | ||
38 | |||
35 | static char *bits_names(unsigned int bits, char *names[], int size) | 39 | static char *bits_names(unsigned int bits, char *names[], int size) |
36 | { | 40 | { |
37 | int i, n; | 41 | int i, n; |
@@ -119,9 +123,8 @@ static void print_amp_caps(struct snd_info_buffer *buffer, | |||
119 | struct hda_codec *codec, hda_nid_t nid, int dir) | 123 | struct hda_codec *codec, hda_nid_t nid, int dir) |
120 | { | 124 | { |
121 | unsigned int caps; | 125 | unsigned int caps; |
122 | caps = snd_hda_param_read(codec, nid, | 126 | caps = param_read(codec, nid, dir == HDA_OUTPUT ? |
123 | dir == HDA_OUTPUT ? | 127 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); |
124 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | ||
125 | if (caps == -1 || caps == 0) { | 128 | if (caps == -1 || caps == 0) { |
126 | snd_iprintf(buffer, "N/A\n"); | 129 | snd_iprintf(buffer, "N/A\n"); |
127 | return; | 130 | return; |
@@ -225,8 +228,8 @@ static void print_pcm_formats(struct snd_info_buffer *buffer, | |||
225 | static void print_pcm_caps(struct snd_info_buffer *buffer, | 228 | static void print_pcm_caps(struct snd_info_buffer *buffer, |
226 | struct hda_codec *codec, hda_nid_t nid) | 229 | struct hda_codec *codec, hda_nid_t nid) |
227 | { | 230 | { |
228 | unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM); | 231 | unsigned int pcm = param_read(codec, nid, AC_PAR_PCM); |
229 | unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 232 | unsigned int stream = param_read(codec, nid, AC_PAR_STREAM); |
230 | if (pcm == -1 || stream == -1) { | 233 | if (pcm == -1 || stream == -1) { |
231 | snd_iprintf(buffer, "N/A\n"); | 234 | snd_iprintf(buffer, "N/A\n"); |
232 | return; | 235 | return; |
@@ -273,7 +276,7 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
273 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | 276 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; |
274 | unsigned int caps, val; | 277 | unsigned int caps, val; |
275 | 278 | ||
276 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 279 | caps = param_read(codec, nid, AC_PAR_PIN_CAP); |
277 | snd_iprintf(buffer, " Pincap 0x%08x:", caps); | 280 | snd_iprintf(buffer, " Pincap 0x%08x:", caps); |
278 | if (caps & AC_PINCAP_IN) | 281 | if (caps & AC_PINCAP_IN) |
279 | snd_iprintf(buffer, " IN"); | 282 | snd_iprintf(buffer, " IN"); |
@@ -401,8 +404,7 @@ static void print_pin_ctls(struct snd_info_buffer *buffer, | |||
401 | static void print_vol_knob(struct snd_info_buffer *buffer, | 404 | static void print_vol_knob(struct snd_info_buffer *buffer, |
402 | struct hda_codec *codec, hda_nid_t nid) | 405 | struct hda_codec *codec, hda_nid_t nid) |
403 | { | 406 | { |
404 | unsigned int cap = snd_hda_param_read(codec, nid, | 407 | unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP); |
405 | AC_PAR_VOL_KNB_CAP); | ||
406 | snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ", | 408 | snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ", |
407 | (cap >> 7) & 1, cap & 0x7f); | 409 | (cap >> 7) & 1, cap & 0x7f); |
408 | cap = snd_hda_codec_read(codec, nid, 0, | 410 | cap = snd_hda_codec_read(codec, nid, 0, |
@@ -487,7 +489,7 @@ static void print_power_state(struct snd_info_buffer *buffer, | |||
487 | [ilog2(AC_PWRST_EPSS)] = "EPSS", | 489 | [ilog2(AC_PWRST_EPSS)] = "EPSS", |
488 | }; | 490 | }; |
489 | 491 | ||
490 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); | 492 | int sup = param_read(codec, nid, AC_PAR_POWER_STATE); |
491 | int pwr = snd_hda_codec_read(codec, nid, 0, | 493 | int pwr = snd_hda_codec_read(codec, nid, 0, |
492 | AC_VERB_GET_POWER_STATE, 0); | 494 | AC_VERB_GET_POWER_STATE, 0); |
493 | if (sup != -1) | 495 | if (sup != -1) |
@@ -531,8 +533,7 @@ static void print_proc_caps(struct snd_info_buffer *buffer, | |||
531 | struct hda_codec *codec, hda_nid_t nid) | 533 | struct hda_codec *codec, hda_nid_t nid) |
532 | { | 534 | { |
533 | unsigned int i, ncoeff, oldindex; | 535 | unsigned int i, ncoeff, oldindex; |
534 | unsigned int proc_caps = snd_hda_param_read(codec, nid, | 536 | unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP); |
535 | AC_PAR_PROC_CAP); | ||
536 | ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT; | 537 | ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT; |
537 | snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n", | 538 | snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n", |
538 | proc_caps & AC_PCAP_BENIGN, ncoeff); | 539 | proc_caps & AC_PCAP_BENIGN, ncoeff); |
@@ -597,7 +598,7 @@ static void print_gpio(struct snd_info_buffer *buffer, | |||
597 | struct hda_codec *codec, hda_nid_t nid) | 598 | struct hda_codec *codec, hda_nid_t nid) |
598 | { | 599 | { |
599 | unsigned int gpio = | 600 | unsigned int gpio = |
600 | snd_hda_param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP); | 601 | param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP); |
601 | unsigned int enable, direction, wake, unsol, sticky, data; | 602 | unsigned int enable, direction, wake, unsol, sticky, data; |
602 | int i, max; | 603 | int i, max; |
603 | snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, " | 604 | snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, " |
@@ -727,8 +728,7 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
727 | 728 | ||
728 | for (i = 0; i < nodes; i++, nid++) { | 729 | for (i = 0; i < nodes; i++, nid++) { |
729 | unsigned int wid_caps = | 730 | unsigned int wid_caps = |
730 | snd_hda_param_read(codec, nid, | 731 | param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); |
731 | AC_PAR_AUDIO_WIDGET_CAP); | ||
732 | unsigned int wid_type = get_wcaps_type(wid_caps); | 732 | unsigned int wid_type = get_wcaps_type(wid_caps); |
733 | hda_nid_t *conn = NULL; | 733 | hda_nid_t *conn = NULL; |
734 | int conn_len = 0; | 734 | int conn_len = 0; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2278e83234b5..231f89029779 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -777,7 +777,6 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
777 | return 0; | 777 | return 0; |
778 | 778 | ||
779 | mutex_lock(&codec->control_mutex); | 779 | mutex_lock(&codec->control_mutex); |
780 | codec->cached_write = 1; | ||
781 | path = snd_hda_get_path_from_idx(codec, | 780 | path = snd_hda_get_path_from_idx(codec, |
782 | spec->smux_paths[spec->cur_smux]); | 781 | spec->smux_paths[spec->cur_smux]); |
783 | if (path) | 782 | if (path) |
@@ -786,9 +785,7 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
786 | if (path) | 785 | if (path) |
787 | snd_hda_activate_path(codec, path, true, true); | 786 | snd_hda_activate_path(codec, path, true, true); |
788 | spec->cur_smux = val; | 787 | spec->cur_smux = val; |
789 | codec->cached_write = 0; | ||
790 | mutex_unlock(&codec->control_mutex); | 788 | mutex_unlock(&codec->control_mutex); |
791 | snd_hda_codec_flush_cache(codec); /* flush the updates */ | ||
792 | return 1; | 789 | return 1; |
793 | } | 790 | } |
794 | 791 | ||
@@ -1004,18 +1001,17 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec, | |||
1004 | const struct hda_fixup *fix, int action) | 1001 | const struct hda_fixup *fix, int action) |
1005 | { | 1002 | { |
1006 | struct ad198x_spec *spec = codec->spec; | 1003 | struct ad198x_spec *spec = codec->spec; |
1007 | static const struct hda_verb gpio_init_verbs[] = { | ||
1008 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
1009 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
1010 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, | ||
1011 | {}, | ||
1012 | }; | ||
1013 | 1004 | ||
1014 | switch (action) { | 1005 | switch (action) { |
1015 | case HDA_FIXUP_ACT_PRE_PROBE: | 1006 | case HDA_FIXUP_ACT_PRE_PROBE: |
1016 | spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook; | 1007 | spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook; |
1017 | spec->gen.own_eapd_ctl = 1; | 1008 | spec->gen.own_eapd_ctl = 1; |
1018 | snd_hda_sequence_write_cache(codec, gpio_init_verbs); | 1009 | snd_hda_codec_write_cache(codec, 0x01, 0, |
1010 | AC_VERB_SET_GPIO_MASK, 0x02); | ||
1011 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
1012 | AC_VERB_SET_GPIO_DIRECTION, 0x02); | ||
1013 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
1014 | AC_VERB_SET_GPIO_DATA, 0x02); | ||
1019 | break; | 1015 | break; |
1020 | case HDA_FIXUP_ACT_PROBE: | 1016 | case HDA_FIXUP_ACT_PROBE: |
1021 | if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) | 1017 | if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1e21f9fbd54b..f8f0dfbef149 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -302,6 +302,7 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec, | |||
302 | switch (action) { | 302 | switch (action) { |
303 | case HDA_FIXUP_ACT_PRE_PROBE: | 303 | case HDA_FIXUP_ACT_PRE_PROBE: |
304 | spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC; | 304 | spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC; |
305 | snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410); | ||
305 | break; | 306 | break; |
306 | case HDA_FIXUP_ACT_PROBE: | 307 | case HDA_FIXUP_ACT_PROBE: |
307 | spec->gen.cap_sync_hook = cxt_update_headset_mode_hook; | 308 | spec->gen.cap_sync_hook = cxt_update_headset_mode_hook; |
@@ -409,15 +410,11 @@ static void olpc_xo_automic(struct hda_codec *codec, | |||
409 | struct hda_jack_callback *jack) | 410 | struct hda_jack_callback *jack) |
410 | { | 411 | { |
411 | struct conexant_spec *spec = codec->spec; | 412 | struct conexant_spec *spec = codec->spec; |
412 | int saved_cached_write = codec->cached_write; | ||
413 | 413 | ||
414 | codec->cached_write = 1; | ||
415 | /* in DC mode, we don't handle automic */ | 414 | /* in DC mode, we don't handle automic */ |
416 | if (!spec->dc_enable) | 415 | if (!spec->dc_enable) |
417 | snd_hda_gen_mic_autoswitch(codec, jack); | 416 | snd_hda_gen_mic_autoswitch(codec, jack); |
418 | olpc_xo_update_mic_pins(codec); | 417 | olpc_xo_update_mic_pins(codec); |
419 | snd_hda_codec_flush_cache(codec); | ||
420 | codec->cached_write = saved_cached_write; | ||
421 | if (spec->dc_enable) | 418 | if (spec->dc_enable) |
422 | olpc_xo_update_mic_boost(codec); | 419 | olpc_xo_update_mic_boost(codec); |
423 | } | 420 | } |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 35d92a8a99ce..ca0c05e1c42e 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -2211,8 +2211,7 @@ static int generic_hdmi_resume(struct hda_codec *codec) | |||
2211 | int pin_idx; | 2211 | int pin_idx; |
2212 | 2212 | ||
2213 | codec->patch_ops.init(codec); | 2213 | codec->patch_ops.init(codec); |
2214 | snd_hda_codec_resume_amp(codec); | 2214 | regcache_sync(codec->core.regmap); |
2215 | snd_hda_codec_resume_cache(codec); | ||
2216 | 2215 | ||
2217 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2216 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2218 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2217 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
@@ -2299,6 +2298,7 @@ static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) | |||
2299 | 2298 | ||
2300 | /* enable DP1.2 mode */ | 2299 | /* enable DP1.2 mode */ |
2301 | vendor_param |= INTEL_EN_DP12; | 2300 | vendor_param |= INTEL_EN_DP12; |
2301 | snd_hdac_regmap_add_vendor_verb(&codec->core, INTEL_SET_VENDOR_VERB); | ||
2302 | snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0, | 2302 | snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0, |
2303 | INTEL_SET_VENDOR_VERB, vendor_param); | 2303 | INTEL_SET_VENDOR_VERB, vendor_param); |
2304 | } | 2304 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index eee4532ab5f6..d44cb7e37094 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -799,8 +799,7 @@ static int alc_resume(struct hda_codec *codec) | |||
799 | if (!spec->no_depop_delay) | 799 | if (!spec->no_depop_delay) |
800 | msleep(150); /* to avoid pop noise */ | 800 | msleep(150); /* to avoid pop noise */ |
801 | codec->patch_ops.init(codec); | 801 | codec->patch_ops.init(codec); |
802 | snd_hda_codec_resume_amp(codec); | 802 | regcache_sync(codec->core.regmap); |
803 | snd_hda_codec_resume_cache(codec); | ||
804 | hda_call_check_power_status(codec, 0x01); | 803 | hda_call_check_power_status(codec, 0x01); |
805 | return 0; | 804 | return 0; |
806 | } | 805 | } |
@@ -3058,8 +3057,7 @@ static int alc269_resume(struct hda_codec *codec) | |||
3058 | msleep(200); | 3057 | msleep(200); |
3059 | } | 3058 | } |
3060 | 3059 | ||
3061 | snd_hda_codec_resume_amp(codec); | 3060 | regcache_sync(codec->core.regmap); |
3062 | snd_hda_codec_resume_cache(codec); | ||
3063 | hda_call_check_power_status(codec, 0x01); | 3061 | hda_call_check_power_status(codec, 0x01); |
3064 | 3062 | ||
3065 | /* on some machine, the BIOS will clear the codec gpio data when enter | 3063 | /* on some machine, the BIOS will clear the codec gpio data when enter |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 49b4868797a5..5104bebb2286 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -222,6 +222,10 @@ static int si3054_init(struct hda_codec *codec) | |||
222 | unsigned wait_count; | 222 | unsigned wait_count; |
223 | u16 val; | 223 | u16 val; |
224 | 224 | ||
225 | if (snd_hdac_regmap_add_vendor_verb(&codec->core, | ||
226 | SI3054_VERB_WRITE_NODE)) | ||
227 | return -ENOMEM; | ||
228 | |||
225 | snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); | 229 | snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); |
226 | snd_hda_codec_write(codec, codec->core.mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0); | 230 | snd_hda_codec_write(codec, codec->core.mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0); |
227 | SET_REG(codec, SI3054_LINE_RATE, 9600); | 231 | SET_REG(codec, SI3054_LINE_RATE, 9600); |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b314551749f1..43c99ce4a520 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1050,12 +1050,9 @@ static const struct hda_verb stac92hd71bxx_core_init[] = { | |||
1050 | {} | 1050 | {} |
1051 | }; | 1051 | }; |
1052 | 1052 | ||
1053 | static const struct hda_verb stac92hd71bxx_unmute_core_init[] = { | 1053 | static const hda_nid_t stac92hd71bxx_unmute_nids[] = { |
1054 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ | 1054 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ |
1055 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1055 | 0x0f, 0x0a, 0x0d, 0 |
1056 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1057 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1058 | {} | ||
1059 | }; | 1056 | }; |
1060 | 1057 | ||
1061 | static const struct hda_verb stac925x_core_init[] = { | 1058 | static const struct hda_verb stac925x_core_init[] = { |
@@ -4269,6 +4266,10 @@ static int stac_parse_auto_config(struct hda_codec *codec) | |||
4269 | 4266 | ||
4270 | if (spec->aloopback_ctl && | 4267 | if (spec->aloopback_ctl && |
4271 | snd_hda_get_bool_hint(codec, "loopback") == 1) { | 4268 | snd_hda_get_bool_hint(codec, "loopback") == 1) { |
4269 | unsigned int wr_verb = | ||
4270 | spec->aloopback_ctl->private_value >> 16; | ||
4271 | if (snd_hdac_regmap_add_vendor_verb(&codec->core, wr_verb)) | ||
4272 | return -ENOMEM; | ||
4272 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl)) | 4273 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl)) |
4273 | return -ENOMEM; | 4274 | return -ENOMEM; |
4274 | } | 4275 | } |
@@ -4688,7 +4689,7 @@ static int patch_stac92hd95(struct hda_codec *codec) | |||
4688 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 4689 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
4689 | { | 4690 | { |
4690 | struct sigmatel_spec *spec; | 4691 | struct sigmatel_spec *spec; |
4691 | const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; | 4692 | const hda_nid_t *unmute_nids = stac92hd71bxx_unmute_nids; |
4692 | int err; | 4693 | int err; |
4693 | 4694 | ||
4694 | err = alloc_stac_spec(codec); | 4695 | err = alloc_stac_spec(codec); |
@@ -4713,7 +4714,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4713 | switch (codec->core.vendor_id) { | 4714 | switch (codec->core.vendor_id) { |
4714 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 4715 | case 0x111d76b6: /* 4 Port without Analog Mixer */ |
4715 | case 0x111d76b7: | 4716 | case 0x111d76b7: |
4716 | unmute_init++; | 4717 | unmute_nids++; |
4717 | break; | 4718 | break; |
4718 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 4719 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
4719 | if ((codec->core.revision_id & 0xf) == 0 || | 4720 | if ((codec->core.revision_id & 0xf) == 0 || |
@@ -4721,7 +4722,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4721 | spec->stream_delay = 40; /* 40 milliseconds */ | 4722 | spec->stream_delay = 40; /* 40 milliseconds */ |
4722 | 4723 | ||
4723 | /* disable VSW */ | 4724 | /* disable VSW */ |
4724 | unmute_init++; | 4725 | unmute_nids++; |
4725 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 4726 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
4726 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 4727 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
4727 | break; | 4728 | break; |
@@ -4735,8 +4736,12 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4735 | if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) | 4736 | if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) |
4736 | snd_hda_add_verbs(codec, stac92hd71bxx_core_init); | 4737 | snd_hda_add_verbs(codec, stac92hd71bxx_core_init); |
4737 | 4738 | ||
4738 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) | 4739 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) { |
4739 | snd_hda_sequence_write_cache(codec, unmute_init); | 4740 | const hda_nid_t *p; |
4741 | for (p = unmute_nids; *p; p++) | ||
4742 | snd_hda_codec_amp_init_stereo(codec, *p, HDA_INPUT, 0, | ||
4743 | 0xff, 0x00); | ||
4744 | } | ||
4740 | 4745 | ||
4741 | spec->aloopback_ctl = &stac92hd71bxx_loopback; | 4746 | spec->aloopback_ctl = &stac92hd71bxx_loopback; |
4742 | spec->aloopback_mask = 0x50; | 4747 | spec->aloopback_mask = 0x50; |