On Mon, 07 Mar 2016 15:57:43 +0100, libin.yang@linux.intel.com wrote:
From: Libin Yang libin.yang@linux.intel.com
This patches adds the support of connection list for DP MST. With this, hdmi driver in DP MST mode can easily reuse the connection list mechanism.
Signed-off-by: Libin Yang libin.yang@linux.intel.com
I would just replace the function with *_mst() and provide the old ones via static inline wrappers instead of having two copies.
Takashi
sound/pci/hda/hda_codec.c | 134 ++++++++++++++++++++++++++++++++++++++++++---- sound/pci/hda/hda_codec.h | 5 ++ 2 files changed, 128 insertions(+), 11 deletions(-)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8374188..d4c81f7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -110,23 +110,24 @@ struct hda_conn_list { struct list_head list; int len; hda_nid_t nid;
- int dev_id; hda_nid_t conns[0];
};
/* look up the cached results */ static struct hda_conn_list * -lookup_conn_list(struct hda_codec *codec, hda_nid_t nid) +lookup_conn_list(struct hda_codec *codec, hda_nid_t nid, int dev_id) { struct hda_conn_list *p; list_for_each_entry(p, &codec->conn_list, list) {
if (p->nid == nid)
} return NULL;if ((p->nid == nid) && (p->dev_id == dev_id)) return p;
}
-static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
const hda_nid_t *list)
+static int add_conn_list(struct hda_codec *codec, hda_nid_t nid,
int dev_id, int len, const hda_nid_t *list)
{ struct hda_conn_list *p;
@@ -135,6 +136,7 @@ static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len, return -ENOMEM; p->len = len; p->nid = nid;
- p->dev_id = dev_id; memcpy(p->conns, list, len * sizeof(hda_nid_t)); list_add(&p->list, &codec->conn_list); return 0;
@@ -150,8 +152,13 @@ static void remove_conn_list(struct hda_codec *codec) } }
-/* read the connection and add to the cache */ -static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid) +/*
- read the connection and add to the cache
- the caller should select the device entry by sending the
- corresponding verb if necessary before calling this function
- */
+static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid,
int dev_id)
{ hda_nid_t list[32]; hda_nid_t *result = list; @@ -166,7 +173,8 @@ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid) len = snd_hda_get_raw_connections(codec, nid, result, len); } if (len >= 0)
len = snd_hda_override_conn_list(codec, nid, len, result);
len = snd_hda_override_conn_list_mst(codec, nid,
if (result != list) kfree(result); return len;dev_id, len, result);
@@ -197,7 +205,7 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, const struct hda_conn_list *p;
/* if the connection-list is already cached, read it */
p = lookup_conn_list(codec, nid);
if (p) { if (listp) *listp = p->conns;p = lookup_conn_list(codec, nid, 0);
@@ -206,7 +214,7 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, if (snd_BUG_ON(added)) return -EINVAL;
err = read_and_add_raw_conns(codec, nid);
if (err < 0) return err; added = true;err = read_and_add_raw_conns(codec, nid, 0);
@@ -215,6 +223,49 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
/**
- snd_hda_get_conn_list_mst - get connection list in mst mode
- @codec: the HDA codec
- @nid: NID to parse
- @dev_id: device entry id
- @listp: the pointer to store NID list
- Parses the connection list of the given widget and stores the pointer
- to the list of NIDs.
- Returns the number of connections, or a negative error code.
- Note that the returned pointer isn't protected against the list
- modification. If snd_hda_override_conn_list() might be called
- concurrently, protect with a mutex appropriately.
- */
+int snd_hda_get_conn_list_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, const hda_nid_t **listp)
+{
- bool added = false;
- for (;;) {
int err;
const struct hda_conn_list *p;
/* if the connection-list is already cached, read it */
p = lookup_conn_list(codec, nid, dev_id);
if (p) {
if (listp)
*listp = p->conns;
return p->len;
}
if (snd_BUG_ON(added))
return -EINVAL;
err = read_and_add_raw_conns(codec, nid, dev_id);
if (err < 0)
return err;
added = true;
- }
+} +EXPORT_SYMBOL_GPL(snd_hda_get_conn_list_mst);
+/**
- snd_hda_get_connections - copy connection list
- @codec: the HDA codec
- @nid: NID to parse
@@ -246,6 +297,39 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, EXPORT_SYMBOL_GPL(snd_hda_get_connections);
/**
- snd_hda_get_connections_mst - copy connection list in mst mode
- @codec: the HDA codec
- @nid: NID to parse
- @dev_id: device entry id
- @conn_list: connection list array; when NULL, checks only the size
- @max_conns: max. number of connections to store
- Parses the connection list of the given widget and stores the list
- of NIDs.
- Returns the number of connections, or a negative error code.
- */
+int snd_hda_get_connections_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, hda_nid_t *conn_list,
int max_conns)
+{
- const hda_nid_t *list;
- int len = snd_hda_get_conn_list_mst(codec, nid, dev_id, &list);
- if (len > 0 && conn_list) {
if (len > max_conns) {
codec_err(codec, "Too many connections %d for NID 0x%x\n",
len, nid);
return -EINVAL;
}
memcpy(conn_list, list, len * sizeof(hda_nid_t));
- }
- return len;
+} +EXPORT_SYMBOL_GPL(snd_hda_get_connections_mst);
+/**
- snd_hda_override_conn_list - add/modify the connection-list to cache
- @codec: the HDA codec
- @nid: NID to parse
@@ -262,17 +346,45 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len, { struct hda_conn_list *p;
- p = lookup_conn_list(codec, nid);
- p = lookup_conn_list(codec, nid, 0); if (p) { list_del(&p->list); kfree(p); }
- return add_conn_list(codec, nid, len, list);
- return add_conn_list(codec, nid, 0, len, list);
} EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
/**
- snd_hda_override_conn_list_mst - add/modify the connection-list to cache
- @codec: the HDA codec
- @nid: NID to parse
- @dev_id: device entry id
- @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_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, int len, const hda_nid_t *list)
+{
- struct hda_conn_list *p;
- p = lookup_conn_list(codec, nid, dev_id);
- if (p) {
list_del(&p->list);
kfree(p);
- }
- return add_conn_list(codec, nid, dev_id, len, list);
+} +EXPORT_SYMBOL_GPL(snd_hda_override_conn_list_mst);
+/**
- snd_hda_get_conn_index - get the connection index of the given NID
- @codec: the HDA codec
- @mux: NID containing the list
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 373fcad..deeed35 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -330,6 +330,9 @@ snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, snd_hdac_get_sub_nodes(&(codec)->core, nid, start_nid) 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_connections_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, hda_nid_t *conn_list,
int max_conns);
static inline int snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid) { @@ -345,6 +348,8 @@ 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_override_conn_list_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, int len, 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_get_devices(struct hda_codec *codec, hda_nid_t nid, -- 1.9.1