mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
topology: add support for CTL access flags to config file
Allow the config files to define CTL access flags. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d1784ad804
commit
f5e0062258
2 changed files with 161 additions and 4 deletions
|
|
@ -93,6 +93,35 @@ extern "C" {
|
||||||
* * range
|
* * range
|
||||||
* * strobe
|
* * 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>
|
* <h5>Control TLV Data</h5>
|
||||||
* Controls can also use TLV data to represent dB information. This can be done
|
* 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.
|
* by defining a TLV section and using the TLV section within the control.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,88 @@
|
||||||
|
|
||||||
#define ENUM_VAL_SIZE (SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
|
#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 */
|
/* copy referenced TLV to the mixer control */
|
||||||
static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
|
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;
|
snd_config_t *n;
|
||||||
const char *id, *val = NULL;
|
const char *id, *val = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
bool access_set = false, tlv_set = false;
|
||||||
|
|
||||||
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
|
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
|
||||||
if (!elem)
|
if (!elem)
|
||||||
|
|
@ -380,8 +463,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
be->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
tlv_set = true;
|
||||||
SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
|
||||||
tplg_dbg("\t%s: %s\n", id, val);
|
tplg_dbg("\t%s: %s\n", id, val);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -401,6 +483,22 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
|
||||||
return err;
|
return err;
|
||||||
continue;
|
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;
|
return 0;
|
||||||
|
|
@ -416,6 +514,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||||
snd_config_t *n;
|
snd_config_t *n;
|
||||||
const char *id, *val = NULL;
|
const char *id, *val = NULL;
|
||||||
int err, j;
|
int err, j;
|
||||||
|
bool access_set = false;
|
||||||
|
|
||||||
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
|
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
|
||||||
if (!elem)
|
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);
|
tplg_dbg("\t%s: %s\n", id, val);
|
||||||
continue;
|
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;
|
return 0;
|
||||||
|
|
@ -513,6 +625,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||||
snd_config_t *n;
|
snd_config_t *n;
|
||||||
const char *id, *val = NULL;
|
const char *id, *val = NULL;
|
||||||
int err, j;
|
int err, j;
|
||||||
|
bool access_set = false, tlv_set = false;
|
||||||
|
|
||||||
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
|
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
|
||||||
if (!elem)
|
if (!elem)
|
||||||
|
|
@ -606,8 +719,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
tlv_set = true;
|
||||||
SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
|
||||||
tplg_dbg("\t%s: %s\n", id, val);
|
tplg_dbg("\t%s: %s\n", id, val);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -620,6 +732,22 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
|
||||||
tplg_dbg("\t%s: %s\n", id, val);
|
tplg_dbg("\t%s: %s\n", id, val);
|
||||||
continue;
|
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;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue