topology: add support for CTL access flags to config file
diff mbox

Message ID 1457942858-5652-4-git-send-email-liam.r.girdwood@linux.intel.com
State New
Headers show

Commit Message

Liam Girdwood March 14, 2016, 8:07 a.m. UTC
Allow the config files to define CTL access flags.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
---
 include/topology.h |  29 ++++++++++++
 src/topology/ctl.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 161 insertions(+), 4 deletions(-)

Comments

Takashi Iwai March 14, 2016, 3:58 p.m. UTC | #1
On Mon, 14 Mar 2016 09:07:37 +0100,
Liam Girdwood wrote:
> 
> Allow the config files to define CTL access flags.
> 
> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>

Applied, thanks.


Takashi

> ---
>  include/topology.h |  29 ++++++++++++
>  src/topology/ctl.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 161 insertions(+), 4 deletions(-)
> 
> diff --git a/include/topology.h b/include/topology.h
> index 993537c..011f6ae 100644
> --- a/include/topology.h
> +++ b/include/topology.h
> @@ -93,6 +93,35 @@ extern "C" {
>   *  * range
>   *  * strobe
>   *
> +* <h5>Control Access</h5>
> + * Controls access can be specified using the "access" section. If no "access"
> + * section is defined then default RW access flags are set for normal and TLV
> + * controls.
> + *
> + * <pre>
> + *	access [
> + *		read
> + *		write
> + *		tlv_command
> + *	]
> + * </pre>
> + *
> + * The standard access flags are as follows :-
> + *  * read
> + *  * write
> + *  * read_write
> + *  * volatile
> + *  * timestamp
> + *  * tlv_read
> + *  * tlv_write
> + *  * tlv_read_write
> + *  * tlv_command
> + *  * inactive
> + *  * lock
> + *  * owner
> + *  * tlv_callback
> + *  * user
> + *
>   * <h5>Control TLV Data</h5>
>   * Controls can also use TLV data to represent dB information. This can be done
>   * by defining a TLV section and using the TLV section within the control.
> diff --git a/src/topology/ctl.c b/src/topology/ctl.c
> index 23c196a..b948ac0 100644
> --- a/src/topology/ctl.c
> +++ b/src/topology/ctl.c
> @@ -21,6 +21,88 @@
>  
>  #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
>  
> +struct ctl_access_elem {
> +	const char *name;
> +	unsigned int value;
> +};
> +
> +/* CTL access strings and codes */
> +static const struct ctl_access_elem ctl_access[] = {
> +	{"read", SNDRV_CTL_ELEM_ACCESS_READ},
> +	{"write", SNDRV_CTL_ELEM_ACCESS_WRITE},
> +	{"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE},
> +	{"volatile", SNDRV_CTL_ELEM_ACCESS_VOLATILE},
> +	{"timestamp", SNDRV_CTL_ELEM_ACCESS_TIMESTAMP},
> +	{"tlv_read", SNDRV_CTL_ELEM_ACCESS_TLV_READ},
> +	{"tlv_write", SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
> +	{"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE},
> +	{"tlv_command", SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
> +	{"inactive", SNDRV_CTL_ELEM_ACCESS_INACTIVE},
> +	{"lock", SNDRV_CTL_ELEM_ACCESS_LOCK},
> +	{"owner", SNDRV_CTL_ELEM_ACCESS_OWNER},
> +	{"tlv_callback", SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK},
> +	{"user", SNDRV_CTL_ELEM_ACCESS_USER},
> +};
> +
> +/* find CTL access strings and conver to values */
> +static int parse_access_values(snd_config_t *cfg,
> +	struct snd_soc_tplg_ctl_hdr *hdr)
> +{
> +	snd_config_iterator_t i, next;
> +	snd_config_t *n;
> +	const char *value = NULL;
> +	unsigned int j;
> +
> +	tplg_dbg(" Access:\n");
> +
> +	snd_config_for_each(i, next, cfg) {
> +		n = snd_config_iterator_entry(i);
> +
> +		/* get value */
> +		if (snd_config_get_string(n, &value) < 0)
> +			continue;
> +
> +		/* match access value and set flags */
> +		for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
> +			if (strcmp(value, ctl_access[j].name) == 0) {
> +				hdr->access |= ctl_access[j].value;
> +				tplg_dbg("\t%s\n", value);
> +				break;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/* Parse Access */
> +int parse_access(snd_config_t *cfg,
> +	struct snd_soc_tplg_ctl_hdr *hdr)
> +{
> +	snd_config_iterator_t i, next;
> +	snd_config_t *n;
> +	const char *id;
> +	int err = 0;
> +
> +	snd_config_for_each(i, next, cfg) {
> +
> +		n = snd_config_iterator_entry(i);
> +		if (snd_config_get_id(n, &id) < 0)
> +			continue;
> +
> +		if (strcmp(id, "access") == 0) {
> +			err = parse_access_values(n, hdr);
> +			if (err < 0) {
> +				SNDERR("error: failed to parse access");
> +				return err;
> +			}
> +			continue;
> +		}
> +	}
> +
> +	return err;
> +}
> +
>  /* copy referenced TLV to the mixer control */
>  static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
>  {
> @@ -295,6 +377,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
>  	snd_config_t *n;
>  	const char *id, *val = NULL;
>  	int err;
> +	bool access_set = false, tlv_set = false;
>  
>  	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
>  	if (!elem)
> @@ -380,8 +463,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
>  			if (err < 0)
>  				return err;
>  
> -			be->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
> -				SNDRV_CTL_ELEM_ACCESS_READWRITE;
> +			tlv_set = true;
>  			tplg_dbg("\t%s: %s\n", id, val);
>  			continue;
>  		}
> @@ -401,6 +483,22 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
>  				return err;
>  			continue;
>  		}
> +
> +		if (strcmp(id, "access") == 0) {
> +			err = parse_access(cfg, &be->hdr);
> +			if (err < 0)
> +				return err;
> +			access_set = true;
> +			continue;
> +		}
> +	}
> +
> +	/* set CTL access to default values if none are provided */
> +	if (!access_set) {
> +
> +		be->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
> +		if (tlv_set)
> +			be->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
>  	}
>  
>  	return 0;
> @@ -416,6 +514,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
>  	snd_config_t *n;
>  	const char *id, *val = NULL;
>  	int err, j;
> +	bool access_set = false;
>  
>  	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
>  	if (!elem)
> @@ -495,6 +594,19 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
>  			tplg_dbg("\t%s: %s\n", id, val);
>  			continue;
>  		}
> +
> +		if (strcmp(id, "access") == 0) {
> +			err = parse_access(cfg, &ec->hdr);
> +			if (err < 0)
> +				return err;
> +			access_set = true;
> +			continue;
> +		}
> +	}
> +
> +	/* set CTL access to default values if none are provided */
> +	if (!access_set) {
> +		ec->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
>  	}
>  
>  	return 0;
> @@ -513,6 +625,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
>  	snd_config_t *n;
>  	const char *id, *val = NULL;
>  	int err, j;
> +	bool access_set = false, tlv_set = false;
>  
>  	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
>  	if (!elem)
> @@ -606,8 +719,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
>  			if (err < 0)
>  				return err;
>  
> -			mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
> -				SNDRV_CTL_ELEM_ACCESS_READWRITE;
> +			tlv_set = true;
>  			tplg_dbg("\t%s: %s\n", id, val);
>  			continue;
>  		}
> @@ -620,6 +732,22 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
>  			tplg_dbg("\t%s: %s\n", id, val);
>  			continue;
>  		}
> +
> +		if (strcmp(id, "access") == 0) {
> +			err = parse_access(cfg, &mc->hdr);
> +			if (err < 0)
> +				return err;
> +			access_set = true;
> +			continue;
> +		}
> +	}
> +
> +	/* set CTL access to default values if none are provided */
> +	if (!access_set) {
> +
> +		mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
> +		if (tlv_set)
> +			mc->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
>  	}
>  
>  	return 0;
> -- 
> 2.5.0
>

Patch
diff mbox

diff --git a/include/topology.h b/include/topology.h
index 993537c..011f6ae 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -93,6 +93,35 @@  extern "C" {
  *  * range
  *  * strobe
  *
+* <h5>Control Access</h5>
+ * Controls access can be specified using the "access" section. If no "access"
+ * section is defined then default RW access flags are set for normal and TLV
+ * controls.
+ *
+ * <pre>
+ *	access [
+ *		read
+ *		write
+ *		tlv_command
+ *	]
+ * </pre>
+ *
+ * The standard access flags are as follows :-
+ *  * read
+ *  * write
+ *  * read_write
+ *  * volatile
+ *  * timestamp
+ *  * tlv_read
+ *  * tlv_write
+ *  * tlv_read_write
+ *  * tlv_command
+ *  * inactive
+ *  * lock
+ *  * owner
+ *  * tlv_callback
+ *  * user
+ *
  * <h5>Control TLV Data</h5>
  * Controls can also use TLV data to represent dB information. This can be done
  * by defining a TLV section and using the TLV section within the control.
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 23c196a..b948ac0 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -21,6 +21,88 @@ 
 
 #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
 
+struct ctl_access_elem {
+	const char *name;
+	unsigned int value;
+};
+
+/* CTL access strings and codes */
+static const struct ctl_access_elem ctl_access[] = {
+	{"read", SNDRV_CTL_ELEM_ACCESS_READ},
+	{"write", SNDRV_CTL_ELEM_ACCESS_WRITE},
+	{"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE},
+	{"volatile", SNDRV_CTL_ELEM_ACCESS_VOLATILE},
+	{"timestamp", SNDRV_CTL_ELEM_ACCESS_TIMESTAMP},
+	{"tlv_read", SNDRV_CTL_ELEM_ACCESS_TLV_READ},
+	{"tlv_write", SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
+	{"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE},
+	{"tlv_command", SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
+	{"inactive", SNDRV_CTL_ELEM_ACCESS_INACTIVE},
+	{"lock", SNDRV_CTL_ELEM_ACCESS_LOCK},
+	{"owner", SNDRV_CTL_ELEM_ACCESS_OWNER},
+	{"tlv_callback", SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK},
+	{"user", SNDRV_CTL_ELEM_ACCESS_USER},
+};
+
+/* find CTL access strings and conver to values */
+static int parse_access_values(snd_config_t *cfg,
+	struct snd_soc_tplg_ctl_hdr *hdr)
+{
+	snd_config_iterator_t i, next;
+	snd_config_t *n;
+	const char *value = NULL;
+	unsigned int j;
+
+	tplg_dbg(" Access:\n");
+
+	snd_config_for_each(i, next, cfg) {
+		n = snd_config_iterator_entry(i);
+
+		/* get value */
+		if (snd_config_get_string(n, &value) < 0)
+			continue;
+
+		/* match access value and set flags */
+		for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
+			if (strcmp(value, ctl_access[j].name) == 0) {
+				hdr->access |= ctl_access[j].value;
+				tplg_dbg("\t%s\n", value);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* Parse Access */
+int parse_access(snd_config_t *cfg,
+	struct snd_soc_tplg_ctl_hdr *hdr)
+{
+	snd_config_iterator_t i, next;
+	snd_config_t *n;
+	const char *id;
+	int err = 0;
+
+	snd_config_for_each(i, next, cfg) {
+
+		n = snd_config_iterator_entry(i);
+		if (snd_config_get_id(n, &id) < 0)
+			continue;
+
+		if (strcmp(id, "access") == 0) {
+			err = parse_access_values(n, hdr);
+			if (err < 0) {
+				SNDERR("error: failed to parse access");
+				return err;
+			}
+			continue;
+		}
+	}
+
+	return err;
+}
+
 /* copy referenced TLV to the mixer control */
 static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
 {
@@ -295,6 +377,7 @@  int tplg_parse_control_bytes(snd_tplg_t *tplg,
 	snd_config_t *n;
 	const char *id, *val = NULL;
 	int err;
+	bool access_set = false, tlv_set = false;
 
 	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
 	if (!elem)
@@ -380,8 +463,7 @@  int tplg_parse_control_bytes(snd_tplg_t *tplg,
 			if (err < 0)
 				return err;
 
-			be->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
-				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+			tlv_set = true;
 			tplg_dbg("\t%s: %s\n", id, val);
 			continue;
 		}
@@ -401,6 +483,22 @@  int tplg_parse_control_bytes(snd_tplg_t *tplg,
 				return err;
 			continue;
 		}
+
+		if (strcmp(id, "access") == 0) {
+			err = parse_access(cfg, &be->hdr);
+			if (err < 0)
+				return err;
+			access_set = true;
+			continue;
+		}
+	}
+
+	/* set CTL access to default values if none are provided */
+	if (!access_set) {
+
+		be->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+		if (tlv_set)
+			be->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
 	}
 
 	return 0;
@@ -416,6 +514,7 @@  int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
 	snd_config_t *n;
 	const char *id, *val = NULL;
 	int err, j;
+	bool access_set = false;
 
 	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
 	if (!elem)
@@ -495,6 +594,19 @@  int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
 			tplg_dbg("\t%s: %s\n", id, val);
 			continue;
 		}
+
+		if (strcmp(id, "access") == 0) {
+			err = parse_access(cfg, &ec->hdr);
+			if (err < 0)
+				return err;
+			access_set = true;
+			continue;
+		}
+	}
+
+	/* set CTL access to default values if none are provided */
+	if (!access_set) {
+		ec->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 	}
 
 	return 0;
@@ -513,6 +625,7 @@  int tplg_parse_control_mixer(snd_tplg_t *tplg,
 	snd_config_t *n;
 	const char *id, *val = NULL;
 	int err, j;
+	bool access_set = false, tlv_set = false;
 
 	elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
 	if (!elem)
@@ -606,8 +719,7 @@  int tplg_parse_control_mixer(snd_tplg_t *tplg,
 			if (err < 0)
 				return err;
 
-			mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
-				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+			tlv_set = true;
 			tplg_dbg("\t%s: %s\n", id, val);
 			continue;
 		}
@@ -620,6 +732,22 @@  int tplg_parse_control_mixer(snd_tplg_t *tplg,
 			tplg_dbg("\t%s: %s\n", id, val);
 			continue;
 		}
+
+		if (strcmp(id, "access") == 0) {
+			err = parse_access(cfg, &mc->hdr);
+			if (err < 0)
+				return err;
+			access_set = true;
+			continue;
+		}
+	}
+
+	/* set CTL access to default values if none are provided */
+	if (!access_set) {
+
+		mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+		if (tlv_set)
+			mc->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
 	}
 
 	return 0;