aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-02-26 02:54:56 -0500
committerTakashi Iwai <tiwai@suse.de>2015-03-23 08:19:40 -0400
commitfaa75f8a2edf005a5caf43be4875ffeeb9bcb498 (patch)
tree5158cb6255a448080b16c376b1006e8e29f946aa /sound/pci
parenteeecd9d10d3da0b9efd6f58fad55c4355dcc246a (diff)
ALSA: hda - Use regmap for parameter caches, too
The amp hash table was used for recording the cached reads of some capability values like pin caps or amp caps. Now all these are moved to regmap as well. One addition to the regmap helper is codec->caps_overwriting flag. This is set in snd_hdac_override_parm(), and the regmap helper accepts any register while this flag is set, so that it can overwrite even the read-only verb like AC_VERB_PARAMETERS. The flag is cleared immediately in snd_hdac_override_parm(), as it's a once-off flag. Along with these changes, the no longer needed amp hash and relevant fields are removed from hda_codec struct now. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c144
-rw-r--r--sound/pci/hda/hda_codec.h7
-rw-r--r--sound/pci/hda/hda_local.h38
3 files changed, 48 insertions, 141 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 */
1384static inline struct hda_amp_info *
1385get_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 */
1391static 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 */
1410static unsigned int
1411query_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
1434static 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 */
1456u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) 1391u32 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}
1462EXPORT_SYMBOL_GPL(query_amp_caps); 1399EXPORT_SYMBOL_GPL(query_amp_caps);
1463 1400
@@ -1498,50 +1435,14 @@ EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
1498int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, 1435int 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}
1503EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
1504
1505static 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 */
1522u32 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}
1527EXPORT_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 */
1539int 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}
1544EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps); 1445EXPORT_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}
3715EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format); 3611EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format);
3716 3612
3717static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid, 3613static 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
3731static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) 3626static 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
3737static 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
3748static 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
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 135b70f066f1..6af801a5bf89 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -163,12 +163,6 @@ struct hda_cache_head {
163 u16 next; 163 u16 next;
164}; 164};
165 165
166struct hda_amp_info {
167 struct hda_cache_head head;
168 u32 amp_caps; /* amp capabilities */
169 u16 vol[2]; /* current volume & mute */
170};
171
172struct hda_cache_rec { 166struct hda_cache_rec {
173 u16 hash[64]; /* hash table for index */ 167 u16 hash[64]; /* hash table for index */
174 struct snd_array buf; /* record entries */ 168 struct snd_array buf; /* record entries */
@@ -257,7 +251,6 @@ struct hda_codec {
257 struct snd_array mixers; /* list of assigned mixer elements */ 251 struct snd_array mixers; /* list of assigned mixer elements */
258 struct snd_array nids; /* list of mapped mixer elements */ 252 struct snd_array nids; /* list of mapped mixer elements */
259 253
260 struct hda_cache_rec amp_cache; /* cache for amp access */
261 struct hda_cache_rec cmd_cache; /* cache for other commands */ 254 struct hda_cache_rec cmd_cache; /* cache for other commands */
262 255
263 struct list_head conn_list; /* linked-list of connection-list */ 256 struct list_head conn_list; /* linked-list of connection-list */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 7023eeee8b9d..3b567f42296b 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -557,9 +557,41 @@ static inline void snd_hda_override_wcaps(struct hda_codec *codec,
557u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); 557u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
558int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, 558int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
559 unsigned int caps); 559 unsigned int caps);
560u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); 560/**
561int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, 561 * snd_hda_query_pin_caps - Query PIN capabilities
562 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 */
571static inline u32
572snd_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 */
588static inline int
589snd_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
563bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid, 595bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
564 int dir, unsigned int bits); 596 int dir, unsigned int bits);
565 597