Blame src/topology/ops.c

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