[alsa-devel] [RFC PATCH 1/4] ALSA: hda - codec add DP MST support for connection list
Takashi Iwai
tiwai at suse.de
Mon Mar 7 17:40:31 CET 2016
On Mon, 07 Mar 2016 15:57:43 +0100,
libin.yang at linux.intel.com wrote:
>
> From: Libin Yang <libin.yang at 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 at 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)
> + if ((p->nid == nid) && (p->dev_id == dev_id))
> return p;
> }
> return NULL;
> }
>
> -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,
> + dev_id, len, result);
> if (result != list)
> kfree(result);
> return len;
> @@ -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);
> + p = lookup_conn_list(codec, nid, 0);
> if (p) {
> if (listp)
> *listp = p->conns;
> @@ -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);
> + err = read_and_add_raw_conns(codec, nid, 0);
> if (err < 0)
> return err;
> added = true;
> @@ -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
>
More information about the Alsa-devel
mailing list