[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