ALSA: hda - Implement uncached version of parameter reads

Sometimes we need the uncached reads, e.g. for refreshing the tree.
This patch provides the helper function for that and uses it for
refreshing widgets, reading subtrees and the whole proc reads.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2015-03-03 23:29:47 +01:00
parent 01ed3c06c6
commit 9ba17b4d13
4 changed files with 43 additions and 17 deletions

View File

@ -107,6 +107,8 @@ int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm, unsigned int *res);
int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm,
unsigned int *res);
int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid,
int parm);
int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,

View File

@ -249,6 +249,29 @@ int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm,
}
EXPORT_SYMBOL_GPL(_snd_hdac_read_parm);
/**
* snd_hdac_read_parm_uncached - read a codec parameter without caching
* @codec: the codec object
* @nid: NID to read a parameter
* @parm: parameter to read
*
* Returns -1 for error. If you need to distinguish the error more
* strictly, use snd_hdac_read() directly.
*/
int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid,
int parm)
{
int val;
if (codec->regmap)
regcache_cache_bypass(codec->regmap, true);
val = snd_hdac_read_parm(codec, nid, parm);
if (codec->regmap)
regcache_cache_bypass(codec->regmap, false);
return val;
}
EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached);
/**
* snd_hdac_get_sub_nodes - get start NID and number of subtree nodes
* @codec: the codec object
@ -256,13 +279,14 @@ EXPORT_SYMBOL_GPL(_snd_hdac_read_parm);
* @start_id: the pointer to store the starting NID
*
* Returns the number of subtree nodes or zero if not found.
* This function reads parameters always without caching.
*/
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
hda_nid_t *start_id)
{
unsigned int parm;
parm = snd_hdac_read_parm(codec, nid, AC_PAR_NODE_COUNT);
parm = snd_hdac_read_parm_uncached(codec, nid, AC_PAR_NODE_COUNT);
if (parm == -1) {
*start_id = 0;
return 0;

View File

@ -586,8 +586,8 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
return -ENOMEM;
nid = codec->core.start_nid;
for (i = 0; i < codec->core.num_nodes; i++, nid++)
codec->wcaps[i] = snd_hda_param_read(codec, nid,
AC_PAR_AUDIO_WIDGET_CAP);
codec->wcaps[i] = snd_hdac_read_parm_uncached(&codec->core,
nid, AC_PAR_AUDIO_WIDGET_CAP);
return 0;
}

View File

@ -32,6 +32,10 @@ static int dump_coef = -1;
module_param(dump_coef, int, 0644);
MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)");
/* always use noncached version */
#define param_read(codec, nid, parm) \
snd_hdac_read_parm_uncached(&(codec)->core, nid, parm)
static char *bits_names(unsigned int bits, char *names[], int size)
{
int i, n;
@ -119,9 +123,8 @@ static void print_amp_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid, int dir)
{
unsigned int caps;
caps = snd_hda_param_read(codec, nid,
dir == HDA_OUTPUT ?
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
caps = param_read(codec, nid, dir == HDA_OUTPUT ?
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
if (caps == -1 || caps == 0) {
snd_iprintf(buffer, "N/A\n");
return;
@ -225,8 +228,8 @@ static void print_pcm_formats(struct snd_info_buffer *buffer,
static void print_pcm_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
unsigned int pcm = param_read(codec, nid, AC_PAR_PCM);
unsigned int stream = param_read(codec, nid, AC_PAR_STREAM);
if (pcm == -1 || stream == -1) {
snd_iprintf(buffer, "N/A\n");
return;
@ -273,7 +276,7 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
unsigned int caps, val;
caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
caps = param_read(codec, nid, AC_PAR_PIN_CAP);
snd_iprintf(buffer, " Pincap 0x%08x:", caps);
if (caps & AC_PINCAP_IN)
snd_iprintf(buffer, " IN");
@ -401,8 +404,7 @@ static void print_pin_ctls(struct snd_info_buffer *buffer,
static void print_vol_knob(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
unsigned int cap = snd_hda_param_read(codec, nid,
AC_PAR_VOL_KNB_CAP);
unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP);
snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ",
(cap >> 7) & 1, cap & 0x7f);
cap = snd_hda_codec_read(codec, nid, 0,
@ -487,7 +489,7 @@ static void print_power_state(struct snd_info_buffer *buffer,
[ilog2(AC_PWRST_EPSS)] = "EPSS",
};
int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE);
int sup = param_read(codec, nid, AC_PAR_POWER_STATE);
int pwr = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_POWER_STATE, 0);
if (sup != -1)
@ -531,8 +533,7 @@ static void print_proc_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
unsigned int i, ncoeff, oldindex;
unsigned int proc_caps = snd_hda_param_read(codec, nid,
AC_PAR_PROC_CAP);
unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP);
ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT;
snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n",
proc_caps & AC_PCAP_BENIGN, ncoeff);
@ -597,7 +598,7 @@ static void print_gpio(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
unsigned int gpio =
snd_hda_param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
unsigned int enable, direction, wake, unsol, sticky, data;
int i, max;
snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
@ -727,8 +728,7 @@ static void print_codec_info(struct snd_info_entry *entry,
for (i = 0; i < nodes; i++, nid++) {
unsigned int wid_caps =
snd_hda_param_read(codec, nid,
AC_PAR_AUDIO_WIDGET_CAP);
param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
unsigned int wid_type = get_wcaps_type(wid_caps);
hda_nid_t *conn = NULL;
int conn_len = 0;