Skip to content

Commit

Permalink
ALSA: hda - Add snd_hda_override_conn_list() helper function
Browse files Browse the repository at this point in the history
Add a function to add/modify the connection-list cache entry.
It'll be useful to fix a buggy hardware result.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Jul 12, 2011
1 parent 1911059 commit b2f934a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 30 deletions.
99 changes: 69 additions & 30 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,23 @@ EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);

static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
static bool add_conn_list(struct snd_array *array, hda_nid_t nid);

/* look up the cached results */
static hda_nid_t *lookup_conn_list(struct snd_array *array, hda_nid_t nid)
{
int i, len;
for (i = 0; i < array->used; ) {
hda_nid_t *p = snd_array_elem(array, i);
if (nid == *p)
return p;
len = p[1];
i += len + 2;
}
return NULL;
}

/**
* snd_hda_get_connections - get connection list
* snd_hda_get_conn_list - get connection list
* @codec: the HDA codec
* @nid: NID to parse
* @listp: the pointer to store NID list
Expand All @@ -327,42 +340,31 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
const hda_nid_t **listp)
{
struct snd_array *array = &codec->conn_lists;
int i, len, old_used;
int len, err;
hda_nid_t list[HDA_MAX_CONNECTIONS];
hda_nid_t *p;
bool added = false;

/* look up the cached results */
for (i = 0; i < array->used; ) {
p = snd_array_elem(array, i);
len = p[1];
if (nid == *p) {
if (listp)
*listp = p + 2;
return len;
}
i += len + 2;
again:
/* if the connection-list is already cached, read it */
p = lookup_conn_list(array, nid);
if (p) {
if (listp)
*listp = p + 2;
return p[1];
}
if (snd_BUG_ON(added))
return -EINVAL;

/* read the connection and add to the cache */
len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
if (len < 0)
return len;

/* add to the cache */
old_used = array->used;
if (!add_conn_list(array, nid) || !add_conn_list(array, len))
goto error_add;
for (i = 0; i < len; i++)
if (!add_conn_list(array, list[i]))
goto error_add;

p = snd_array_elem(array, old_used);
if (listp)
*listp = p + 2;
return len;

error_add:
array->used = old_used;
return -ENOMEM;
err = snd_hda_override_conn_list(codec, nid, len, list);
if (err < 0)
return err;
added = true;
goto again;
}
EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);

Expand Down Expand Up @@ -502,6 +504,43 @@ static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
return true;
}

/**
* snd_hda_override_conn_list - add/modify the connection-list to cache
* @codec: the HDA codec
* @nid: NID to parse
* @len: number of connection list entries
* @list: the list of connection entries
*
* Add or modify the given connection-list to the cache. If the corresponding
* cache already exists, invalidate it and append a new one.
*
* Returns zero or a negative error code.
*/
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
const hda_nid_t *list)
{
struct snd_array *array = &codec->conn_lists;
hda_nid_t *p;
int i, old_used;

p = lookup_conn_list(array, nid);
if (p)
*p = -1; /* invalidate the old entry */

old_used = array->used;
if (!add_conn_list(array, nid) || !add_conn_list(array, len))
goto error_add;
for (i = 0; i < len; i++)
if (!add_conn_list(array, list[i]))
goto error_add;
return 0;

error_add:
array->used = old_used;
return -ENOMEM;
}
EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);

/**
* snd_hda_get_conn_index - get the connection index of the given NID
* @codec: the HDA codec
Expand Down
2 changes: 2 additions & 0 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
const hda_nid_t **listp);
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
const hda_nid_t *list);
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
hda_nid_t nid, int recursive);
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Expand Down

0 comments on commit b2f934a

Please sign in to comment.