Blame src/topology/channel.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 channel text names to types */
Packit Service db8eaa
static const struct map_elem channel_map[] = {
Packit Service db8eaa
	{"mono", SNDRV_CHMAP_MONO},	/* mono stream */
Packit Service db8eaa
	{"fl", SNDRV_CHMAP_FL},		/* front left */
Packit Service db8eaa
	{"fr", SNDRV_CHMAP_FR},		/* front right */
Packit Service db8eaa
	{"rl", SNDRV_CHMAP_RL},		/* rear left */
Packit Service db8eaa
	{"rr", SNDRV_CHMAP_RR},		/* rear right */
Packit Service db8eaa
	{"fc", SNDRV_CHMAP_FC},		/* front center */
Packit Service db8eaa
	{"lfe", SNDRV_CHMAP_LFE},	/* LFE */
Packit Service db8eaa
	{"sl", SNDRV_CHMAP_SL},		/* side left */
Packit Service db8eaa
	{"sr", SNDRV_CHMAP_SR},		/* side right */
Packit Service db8eaa
	{"rc", SNDRV_CHMAP_RC},		/* rear center */
Packit Service db8eaa
	{"flc", SNDRV_CHMAP_FLC},	/* front left center */
Packit Service db8eaa
	{"frc", SNDRV_CHMAP_FRC},	/* front right center */
Packit Service db8eaa
	{"rlc", SNDRV_CHMAP_RLC},	/* rear left center */
Packit Service db8eaa
	{"rrc", SNDRV_CHMAP_RRC},	/* rear right center */
Packit Service db8eaa
	{"flw", SNDRV_CHMAP_FLW},	/* front left wide */
Packit Service db8eaa
	{"frw", SNDRV_CHMAP_FRW},	/* front right wide */
Packit Service db8eaa
	{"flh", SNDRV_CHMAP_FLH},	/* front left high */
Packit Service db8eaa
	{"fch", SNDRV_CHMAP_FCH},	/* front center high */
Packit Service db8eaa
	{"frh", SNDRV_CHMAP_FRH},	/* front right high */
Packit Service db8eaa
	{"tc", SNDRV_CHMAP_TC},		/* top center */
Packit Service db8eaa
	{"tfl", SNDRV_CHMAP_TFL},	/* top front left */
Packit Service db8eaa
	{"tfr", SNDRV_CHMAP_TFR},	/* top front right */
Packit Service db8eaa
	{"tfc", SNDRV_CHMAP_TFC},	/* top front center */
Packit Service db8eaa
	{"trl", SNDRV_CHMAP_TRL},	/* top rear left */
Packit Service db8eaa
	{"trr", SNDRV_CHMAP_TRR},	/* top rear right */
Packit Service db8eaa
	{"trc", SNDRV_CHMAP_TRC},	/* top rear center */
Packit Service db8eaa
	{"tflc", SNDRV_CHMAP_TFLC},	/* top front left center */
Packit Service db8eaa
	{"tfrc", SNDRV_CHMAP_TFRC},	/* top front right center */
Packit Service db8eaa
	{"tsl", SNDRV_CHMAP_TSL},	/* top side left */
Packit Service db8eaa
	{"tsr", SNDRV_CHMAP_TSR},	/* top side right */
Packit Service db8eaa
	{"llfe", SNDRV_CHMAP_LLFE},	/* left LFE */
Packit Service db8eaa
	{"rlfe", SNDRV_CHMAP_RLFE},	/* right LFE */
Packit Service db8eaa
	{"bc", SNDRV_CHMAP_BC},		/* bottom center */
Packit Service db8eaa
	{"blc", SNDRV_CHMAP_BLC},	/* bottom left center */
Packit Service db8eaa
	{"brc", SNDRV_CHMAP_BRC},	/* bottom right center */
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
static int lookup_channel(const char *c)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
Packit Service db8eaa
		if (strcasecmp(channel_map[i].name, c) == 0) {
Packit Service db8eaa
			return channel_map[i].id;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return -EINVAL;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
const char *tplg_channel_name(int type)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
Packit Service db8eaa
		if (channel_map[i].id == type)
Packit Service db8eaa
			return channel_map[i].name;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return NULL;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/* Parse a channel mapping. */
Packit Service db8eaa
int tplg_parse_channel(snd_tplg_t *tplg, 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_channel *channel = private;
Packit Service db8eaa
	const char *id;
Packit Service db8eaa
	int channel_id, value;
Packit Service db8eaa
Packit Service db8eaa
	if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN)
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
Packit Service db8eaa
	channel += tplg->channel_idx;
Packit Service db8eaa
	snd_config_get_id(cfg, &id;;
Packit Service db8eaa
	tplg_dbg("\tChannel %s at index %d", id, tplg->channel_idx);
Packit Service db8eaa
Packit Service db8eaa
	channel_id = lookup_channel(id);
Packit Service db8eaa
	if (channel_id < 0) {
Packit Service db8eaa
		SNDERR("invalid channel %s", id);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	channel->id = channel_id;
Packit Service db8eaa
	channel->size = sizeof(*channel);
Packit Service db8eaa
	tplg_dbg("\tChan %s = %d", id, channel->id);
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 */
Packit Service db8eaa
		if (tplg_get_integer(n, &value, 0) < 0)
Packit Service db8eaa
			continue;
Packit Service db8eaa
Packit Service db8eaa
		if (strcmp(id, "reg") == 0)
Packit Service db8eaa
			channel->reg = value;
Packit Service db8eaa
		else if (strcmp(id, "shift") == 0)
Packit Service db8eaa
			channel->shift = value;
Packit Service db8eaa
Packit Service db8eaa
		tplg_dbg("\t\t%s = %d", id, value);
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	tplg->channel_idx++;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
Packit Service db8eaa
		       struct snd_soc_tplg_channel *channel,
Packit Service db8eaa
		       unsigned int count, struct tplg_buf *dst,
Packit Service db8eaa
		       const char *pfx)
Packit Service db8eaa
{
Packit Service db8eaa
	struct snd_soc_tplg_channel *c;
Packit Service db8eaa
	const char *s;
Packit Service db8eaa
	unsigned int index;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	if (count == 0)
Packit Service db8eaa
		return 0;
Packit Service db8eaa
	err = tplg_save_printf(dst, pfx, "channel {\n");
Packit Service db8eaa
	for (index = 0; err >= 0 && index < count; index++) {
Packit Service db8eaa
		c = channel + index;
Packit Service db8eaa
		s = tplg_channel_name(c->id);
Packit Service db8eaa
		if (s == NULL)
Packit Service db8eaa
			err = tplg_save_printf(dst, pfx, "\t%u", c->id);
Packit Service db8eaa
		else
Packit Service db8eaa
			err = tplg_save_printf(dst, pfx, "\t%s", s);
Packit Service db8eaa
		if (err >= 0)
Packit Service db8eaa
			err = tplg_save_printf(dst, NULL, " {\n");
Packit Service db8eaa
		if (err >= 0)
Packit Service db8eaa
			err = tplg_save_printf(dst, pfx, "\t\treg %d\n", c->reg);
Packit Service db8eaa
		if (err >= 0 && c->shift > 0)
Packit Service db8eaa
			err = tplg_save_printf(dst, pfx, "\t\tshift %u\n", c->shift);
Packit Service db8eaa
		if (err >= 0)
Packit Service db8eaa
			err = tplg_save_printf(dst, pfx, "\t}\n");
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
}