Blame src/topology/ops.c

Packit 4a16fb
/*
Packit 4a16fb
  Copyright(c) 2014-2015 Intel Corporation
Packit 4a16fb
  All rights reserved.
Packit 4a16fb
Packit 4a16fb
  This library is free software; you can redistribute it and/or modify
Packit 4a16fb
  it under the terms of the GNU Lesser General Public License as
Packit 4a16fb
  published by the Free Software Foundation; either version 2.1 of
Packit 4a16fb
  the License, or (at your option) any later version.
Packit 4a16fb
Packit 4a16fb
  This program is distributed in the hope that it will be useful,
Packit 4a16fb
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4a16fb
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4a16fb
  GNU Lesser General Public License for more details.
Packit 4a16fb
Packit 4a16fb
  Authors: Mengdong Lin <mengdong.lin@intel.com>
Packit 4a16fb
           Yao Jin <yao.jin@intel.com>
Packit 4a16fb
           Liam Girdwood <liam.r.girdwood@linux.intel.com>
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
#include "list.h"
Packit 4a16fb
#include "tplg_local.h"
Packit 4a16fb
Packit 4a16fb
/* mapping of kcontrol text names to types */
Packit 4a16fb
static const struct map_elem control_map[] = {
Packit 4a16fb
	{"volsw", SND_SOC_TPLG_CTL_VOLSW},
Packit 4a16fb
	{"volsw_sx", SND_SOC_TPLG_CTL_VOLSW_SX},
Packit 4a16fb
	{"volsw_xr_sx", SND_SOC_TPLG_CTL_VOLSW_XR_SX},
Packit 4a16fb
	{"enum", SND_SOC_TPLG_CTL_ENUM},
Packit 4a16fb
	{"bytes", SND_SOC_TPLG_CTL_BYTES},
Packit 4a16fb
	{"enum_value", SND_SOC_TPLG_CTL_ENUM_VALUE},
Packit 4a16fb
	{"range", SND_SOC_TPLG_CTL_RANGE},
Packit 4a16fb
	{"strobe", SND_SOC_TPLG_CTL_STROBE},
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
static int lookup_ops(const char *c)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int i;
Packit 4a16fb
Packit 4a16fb
	for (i = 0; i < ARRAY_SIZE(control_map); i++) {
Packit 4a16fb
		if (strcmp(control_map[i].name, c) == 0)
Packit 4a16fb
			return control_map[i].id;
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	/* cant find string name in our table so we use its ID number */
Packit Service f36a15
	return strtol(c, NULL, 0);
Packit Service f36a15
}
Packit Service f36a15
Packit Service f36a15
const char *tplg_ops_name(int type)
Packit Service f36a15
{
Packit Service f36a15
	unsigned int i;
Packit Service f36a15
Packit Service f36a15
	for (i = 0; i < ARRAY_SIZE(control_map); i++) {
Packit Service f36a15
		if (control_map[i].id == type)
Packit Service f36a15
			return control_map[i].name;
Packit Service f36a15
	}
Packit Service f36a15
Packit Service f36a15
	return NULL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Parse Control operations. Ops can come from standard names above or
Packit 4a16fb
 * bespoke driver controls with numbers >= 256
Packit 4a16fb
 */
Packit Service f36a15
int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
Packit Service f36a15
		   void *private)
Packit 4a16fb
{
Packit 4a16fb
	snd_config_iterator_t i, next;
Packit 4a16fb
	snd_config_t *n;
Packit 4a16fb
	struct snd_soc_tplg_ctl_hdr *hdr = private;
Packit 4a16fb
	const char *id, *value;
Packit Service f36a15
	int ival;
Packit 4a16fb
Packit Service f36a15
	tplg_dbg("\tOps");
Packit 4a16fb
	hdr->size = sizeof(*hdr);
Packit 4a16fb
Packit 4a16fb
	snd_config_for_each(i, next, cfg) {
Packit 4a16fb
Packit 4a16fb
		n = snd_config_iterator_entry(i);
Packit 4a16fb
Packit 4a16fb
		/* get id */
Packit 4a16fb
		if (snd_config_get_id(n, &id) < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
Packit 4a16fb
		/* get value - try strings then ints */
Packit Service f36a15
		if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) {
Packit Service f36a15
			if (snd_config_get_string(n, &value) < 0)
Packit Service f36a15
				continue;
Packit Service f36a15
			ival = lookup_ops(value);
Packit Service f36a15
		} else {
Packit Service f36a15
			if (tplg_get_integer(n, &ival, 0))
Packit Service f36a15
				continue;
Packit Service f36a15
		}
Packit 4a16fb
Packit 4a16fb
		if (strcmp(id, "info") == 0)
Packit Service f36a15
			hdr->ops.info = ival;
Packit 4a16fb
		else if (strcmp(id, "put") == 0)
Packit Service f36a15
			hdr->ops.put = ival;
Packit 4a16fb
		else if (strcmp(id, "get") == 0)
Packit Service f36a15
			hdr->ops.get = ival;
Packit 4a16fb
Packit Service f36a15
		tplg_dbg("\t\t%s = %d", id, ival);
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit Service f36a15
/* save control operations */
Packit Service f36a15
int tplg_save_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
Packit Service f36a15
		  struct snd_soc_tplg_ctl_hdr *hdr, char **dst,
Packit Service f36a15
		  const char *pfx)
Packit Service f36a15
{
Packit Service f36a15
	const char *s;
Packit Service f36a15
	int err;
Packit Service f36a15
Packit Service f36a15
	if (hdr->ops.info + hdr->ops.get + hdr->ops.put == 0)
Packit Service f36a15
		return 0;
Packit Service f36a15
	err = tplg_save_printf(dst, pfx, "ops.0 {\n");
Packit Service f36a15
	if (err >= 0 && hdr->ops.info > 0) {
Packit Service f36a15
		s = tplg_ops_name(hdr->ops.info);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tinfo %u\n",
Packit Service f36a15
					       hdr->ops.info);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0 && hdr->ops.get > 0) {
Packit Service f36a15
		s = tplg_ops_name(hdr->ops.get);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tget %u\n",
Packit Service f36a15
					       hdr->ops.get);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tget %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0 && hdr->ops.put > 0) {
Packit Service f36a15
		s = tplg_ops_name(hdr->ops.put);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tput %u\n",
Packit Service f36a15
					       hdr->ops.put);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tput %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0)
Packit Service f36a15
		err = tplg_save_printf(dst, pfx, "}\n");
Packit Service f36a15
	return err;
Packit Service f36a15
}
Packit Service f36a15
Packit 4a16fb
/* Parse External Control operations. Ops can come from standard names above or
Packit 4a16fb
 * bespoke driver controls with numbers >= 256
Packit 4a16fb
 */
Packit 4a16fb
int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
Packit Service f36a15
		       snd_config_t *cfg, void *private)
Packit 4a16fb
{
Packit 4a16fb
	snd_config_iterator_t i, next;
Packit 4a16fb
	snd_config_t *n;
Packit 4a16fb
	struct snd_soc_tplg_bytes_control *be = private;
Packit 4a16fb
	const char *id, *value;
Packit Service f36a15
	int ival;
Packit 4a16fb
Packit Service f36a15
	tplg_dbg("\tExt Ops");
Packit 4a16fb
Packit 4a16fb
	snd_config_for_each(i, next, cfg) {
Packit 4a16fb
Packit 4a16fb
		n = snd_config_iterator_entry(i);
Packit 4a16fb
Packit 4a16fb
		/* get id */
Packit 4a16fb
		if (snd_config_get_id(n, &id) < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
Packit 4a16fb
		/* get value - try strings then ints */
Packit Service f36a15
		if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) {
Packit Service f36a15
			if (snd_config_get_string(n, &value) < 0)
Packit Service f36a15
				continue;
Packit Service f36a15
			ival = lookup_ops(value);
Packit Service f36a15
		} else {
Packit Service f36a15
			if (tplg_get_integer(n, &ival, 0))
Packit Service f36a15
				continue;
Packit Service f36a15
		}
Packit 4a16fb
Packit 4a16fb
		if (strcmp(id, "info") == 0)
Packit Service f36a15
			be->ext_ops.info = ival;
Packit 4a16fb
		else if (strcmp(id, "put") == 0)
Packit Service f36a15
			be->ext_ops.put = ival;
Packit 4a16fb
		else if (strcmp(id, "get") == 0)
Packit Service f36a15
			be->ext_ops.get = ival;
Packit 4a16fb
Packit Service f36a15
		tplg_dbg("\t\t%s = %s", id, value);
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit Service f36a15
Packit Service f36a15
/* save external control operations */
Packit Service f36a15
int tplg_save_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
Packit Service f36a15
		      struct snd_soc_tplg_bytes_control *be,
Packit Service f36a15
		      char **dst, const char *pfx)
Packit Service f36a15
{
Packit Service f36a15
	const char *s;
Packit Service f36a15
	int err;
Packit Service f36a15
Packit Service f36a15
	if (be->ext_ops.info + be->ext_ops.get + be->ext_ops.put == 0)
Packit Service f36a15
		return 0;
Packit Service f36a15
	err = tplg_save_printf(dst, pfx, "extops.0 {\n");
Packit Service f36a15
	if (err >= 0 && be->ext_ops.info > 0) {
Packit Service f36a15
		s = tplg_ops_name(be->ext_ops.info);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tinfo %u\n",
Packit Service f36a15
					       be->ext_ops.info);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0 && be->ext_ops.get > 0) {
Packit Service f36a15
		s = tplg_ops_name(be->ext_ops.get);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tget %u\n",
Packit Service f36a15
					       be->ext_ops.get);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tget %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0 && be->ext_ops.put > 0) {
Packit Service f36a15
		s = tplg_ops_name(be->ext_ops.put);
Packit Service f36a15
		if (s == NULL)
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tput %u\n",
Packit Service f36a15
					       be->ext_ops.put);
Packit Service f36a15
		else
Packit Service f36a15
			err = tplg_save_printf(dst, pfx, "\tput %s\n", s);
Packit Service f36a15
	}
Packit Service f36a15
	if (err >= 0)
Packit Service f36a15
		err = tplg_save_printf(dst, pfx, "}\n");
Packit Service f36a15
	return err;
Packit Service f36a15
}