xref: /third_party/alsa-lib/src/topology/channel.c (revision d5ac70f0)
1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci  Copyright(c) 2014-2015 Intel Corporation
3d5ac70f0Sopenharmony_ci  All rights reserved.
4d5ac70f0Sopenharmony_ci
5d5ac70f0Sopenharmony_ci  This library is free software; you can redistribute it and/or modify
6d5ac70f0Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as
7d5ac70f0Sopenharmony_ci  published by the Free Software Foundation; either version 2.1 of
8d5ac70f0Sopenharmony_ci  the License, or (at your option) any later version.
9d5ac70f0Sopenharmony_ci
10d5ac70f0Sopenharmony_ci  This program is distributed in the hope that it will be useful,
11d5ac70f0Sopenharmony_ci  but WITHOUT ANY WARRANTY; without even the implied warranty of
12d5ac70f0Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13d5ac70f0Sopenharmony_ci  GNU Lesser General Public License for more details.
14d5ac70f0Sopenharmony_ci
15d5ac70f0Sopenharmony_ci  Authors: Mengdong Lin <mengdong.lin@intel.com>
16d5ac70f0Sopenharmony_ci           Yao Jin <yao.jin@intel.com>
17d5ac70f0Sopenharmony_ci           Liam Girdwood <liam.r.girdwood@linux.intel.com>
18d5ac70f0Sopenharmony_ci*/
19d5ac70f0Sopenharmony_ci
20d5ac70f0Sopenharmony_ci#include "tplg_local.h"
21d5ac70f0Sopenharmony_ci
22d5ac70f0Sopenharmony_ci/* mapping of channel text names to types */
23d5ac70f0Sopenharmony_cistatic const struct map_elem channel_map[] = {
24d5ac70f0Sopenharmony_ci	{"mono", SNDRV_CHMAP_MONO},	/* mono stream */
25d5ac70f0Sopenharmony_ci	{"fl", SNDRV_CHMAP_FL},		/* front left */
26d5ac70f0Sopenharmony_ci	{"fr", SNDRV_CHMAP_FR},		/* front right */
27d5ac70f0Sopenharmony_ci	{"rl", SNDRV_CHMAP_RL},		/* rear left */
28d5ac70f0Sopenharmony_ci	{"rr", SNDRV_CHMAP_RR},		/* rear right */
29d5ac70f0Sopenharmony_ci	{"fc", SNDRV_CHMAP_FC},		/* front center */
30d5ac70f0Sopenharmony_ci	{"lfe", SNDRV_CHMAP_LFE},	/* LFE */
31d5ac70f0Sopenharmony_ci	{"sl", SNDRV_CHMAP_SL},		/* side left */
32d5ac70f0Sopenharmony_ci	{"sr", SNDRV_CHMAP_SR},		/* side right */
33d5ac70f0Sopenharmony_ci	{"rc", SNDRV_CHMAP_RC},		/* rear center */
34d5ac70f0Sopenharmony_ci	{"flc", SNDRV_CHMAP_FLC},	/* front left center */
35d5ac70f0Sopenharmony_ci	{"frc", SNDRV_CHMAP_FRC},	/* front right center */
36d5ac70f0Sopenharmony_ci	{"rlc", SNDRV_CHMAP_RLC},	/* rear left center */
37d5ac70f0Sopenharmony_ci	{"rrc", SNDRV_CHMAP_RRC},	/* rear right center */
38d5ac70f0Sopenharmony_ci	{"flw", SNDRV_CHMAP_FLW},	/* front left wide */
39d5ac70f0Sopenharmony_ci	{"frw", SNDRV_CHMAP_FRW},	/* front right wide */
40d5ac70f0Sopenharmony_ci	{"flh", SNDRV_CHMAP_FLH},	/* front left high */
41d5ac70f0Sopenharmony_ci	{"fch", SNDRV_CHMAP_FCH},	/* front center high */
42d5ac70f0Sopenharmony_ci	{"frh", SNDRV_CHMAP_FRH},	/* front right high */
43d5ac70f0Sopenharmony_ci	{"tc", SNDRV_CHMAP_TC},		/* top center */
44d5ac70f0Sopenharmony_ci	{"tfl", SNDRV_CHMAP_TFL},	/* top front left */
45d5ac70f0Sopenharmony_ci	{"tfr", SNDRV_CHMAP_TFR},	/* top front right */
46d5ac70f0Sopenharmony_ci	{"tfc", SNDRV_CHMAP_TFC},	/* top front center */
47d5ac70f0Sopenharmony_ci	{"trl", SNDRV_CHMAP_TRL},	/* top rear left */
48d5ac70f0Sopenharmony_ci	{"trr", SNDRV_CHMAP_TRR},	/* top rear right */
49d5ac70f0Sopenharmony_ci	{"trc", SNDRV_CHMAP_TRC},	/* top rear center */
50d5ac70f0Sopenharmony_ci	{"tflc", SNDRV_CHMAP_TFLC},	/* top front left center */
51d5ac70f0Sopenharmony_ci	{"tfrc", SNDRV_CHMAP_TFRC},	/* top front right center */
52d5ac70f0Sopenharmony_ci	{"tsl", SNDRV_CHMAP_TSL},	/* top side left */
53d5ac70f0Sopenharmony_ci	{"tsr", SNDRV_CHMAP_TSR},	/* top side right */
54d5ac70f0Sopenharmony_ci	{"llfe", SNDRV_CHMAP_LLFE},	/* left LFE */
55d5ac70f0Sopenharmony_ci	{"rlfe", SNDRV_CHMAP_RLFE},	/* right LFE */
56d5ac70f0Sopenharmony_ci	{"bc", SNDRV_CHMAP_BC},		/* bottom center */
57d5ac70f0Sopenharmony_ci	{"blc", SNDRV_CHMAP_BLC},	/* bottom left center */
58d5ac70f0Sopenharmony_ci	{"brc", SNDRV_CHMAP_BRC},	/* bottom right center */
59d5ac70f0Sopenharmony_ci};
60d5ac70f0Sopenharmony_ci
61d5ac70f0Sopenharmony_ci
62d5ac70f0Sopenharmony_cistatic int lookup_channel(const char *c)
63d5ac70f0Sopenharmony_ci{
64d5ac70f0Sopenharmony_ci	unsigned int i;
65d5ac70f0Sopenharmony_ci
66d5ac70f0Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
67d5ac70f0Sopenharmony_ci		if (strcasecmp(channel_map[i].name, c) == 0) {
68d5ac70f0Sopenharmony_ci			return channel_map[i].id;
69d5ac70f0Sopenharmony_ci		}
70d5ac70f0Sopenharmony_ci	}
71d5ac70f0Sopenharmony_ci
72d5ac70f0Sopenharmony_ci	return -EINVAL;
73d5ac70f0Sopenharmony_ci}
74d5ac70f0Sopenharmony_ci
75d5ac70f0Sopenharmony_ciconst char *tplg_channel_name(int type)
76d5ac70f0Sopenharmony_ci{
77d5ac70f0Sopenharmony_ci	unsigned int i;
78d5ac70f0Sopenharmony_ci
79d5ac70f0Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
80d5ac70f0Sopenharmony_ci		if (channel_map[i].id == type)
81d5ac70f0Sopenharmony_ci			return channel_map[i].name;
82d5ac70f0Sopenharmony_ci	}
83d5ac70f0Sopenharmony_ci
84d5ac70f0Sopenharmony_ci	return NULL;
85d5ac70f0Sopenharmony_ci}
86d5ac70f0Sopenharmony_ci
87d5ac70f0Sopenharmony_ci/* Parse a channel mapping. */
88d5ac70f0Sopenharmony_ciint tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
89d5ac70f0Sopenharmony_ci		       void *private)
90d5ac70f0Sopenharmony_ci{
91d5ac70f0Sopenharmony_ci	snd_config_iterator_t i, next;
92d5ac70f0Sopenharmony_ci	snd_config_t *n;
93d5ac70f0Sopenharmony_ci	struct snd_soc_tplg_channel *channel = private;
94d5ac70f0Sopenharmony_ci	const char *id;
95d5ac70f0Sopenharmony_ci	int channel_id, value;
96d5ac70f0Sopenharmony_ci
97d5ac70f0Sopenharmony_ci	if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN)
98d5ac70f0Sopenharmony_ci		return -EINVAL;
99d5ac70f0Sopenharmony_ci
100d5ac70f0Sopenharmony_ci	channel += tplg->channel_idx;
101d5ac70f0Sopenharmony_ci	snd_config_get_id(cfg, &id);
102d5ac70f0Sopenharmony_ci	tplg_dbg("\tChannel %s at index %d", id, tplg->channel_idx);
103d5ac70f0Sopenharmony_ci
104d5ac70f0Sopenharmony_ci	channel_id = lookup_channel(id);
105d5ac70f0Sopenharmony_ci	if (channel_id < 0) {
106d5ac70f0Sopenharmony_ci		SNDERR("invalid channel %s", id);
107d5ac70f0Sopenharmony_ci		return -EINVAL;
108d5ac70f0Sopenharmony_ci	}
109d5ac70f0Sopenharmony_ci
110d5ac70f0Sopenharmony_ci	channel->id = channel_id;
111d5ac70f0Sopenharmony_ci	channel->size = sizeof(*channel);
112d5ac70f0Sopenharmony_ci	tplg_dbg("\tChan %s = %d", id, channel->id);
113d5ac70f0Sopenharmony_ci
114d5ac70f0Sopenharmony_ci	snd_config_for_each(i, next, cfg) {
115d5ac70f0Sopenharmony_ci
116d5ac70f0Sopenharmony_ci		n = snd_config_iterator_entry(i);
117d5ac70f0Sopenharmony_ci
118d5ac70f0Sopenharmony_ci		/* get id */
119d5ac70f0Sopenharmony_ci		if (snd_config_get_id(n, &id) < 0)
120d5ac70f0Sopenharmony_ci			continue;
121d5ac70f0Sopenharmony_ci
122d5ac70f0Sopenharmony_ci		/* get value */
123d5ac70f0Sopenharmony_ci		if (tplg_get_integer(n, &value, 0) < 0)
124d5ac70f0Sopenharmony_ci			continue;
125d5ac70f0Sopenharmony_ci
126d5ac70f0Sopenharmony_ci		if (strcmp(id, "reg") == 0)
127d5ac70f0Sopenharmony_ci			channel->reg = value;
128d5ac70f0Sopenharmony_ci		else if (strcmp(id, "shift") == 0)
129d5ac70f0Sopenharmony_ci			channel->shift = value;
130d5ac70f0Sopenharmony_ci
131d5ac70f0Sopenharmony_ci		tplg_dbg("\t\t%s = %d", id, value);
132d5ac70f0Sopenharmony_ci	}
133d5ac70f0Sopenharmony_ci
134d5ac70f0Sopenharmony_ci	tplg->channel_idx++;
135d5ac70f0Sopenharmony_ci	return 0;
136d5ac70f0Sopenharmony_ci}
137d5ac70f0Sopenharmony_ci
138d5ac70f0Sopenharmony_ciint tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
139d5ac70f0Sopenharmony_ci		       struct snd_soc_tplg_channel *channel,
140d5ac70f0Sopenharmony_ci		       unsigned int count, struct tplg_buf *dst,
141d5ac70f0Sopenharmony_ci		       const char *pfx)
142d5ac70f0Sopenharmony_ci{
143d5ac70f0Sopenharmony_ci	struct snd_soc_tplg_channel *c;
144d5ac70f0Sopenharmony_ci	const char *s;
145d5ac70f0Sopenharmony_ci	unsigned int index;
146d5ac70f0Sopenharmony_ci	int err;
147d5ac70f0Sopenharmony_ci
148d5ac70f0Sopenharmony_ci	if (count == 0)
149d5ac70f0Sopenharmony_ci		return 0;
150d5ac70f0Sopenharmony_ci	err = tplg_save_printf(dst, pfx, "channel {\n");
151d5ac70f0Sopenharmony_ci	for (index = 0; err >= 0 && index < count; index++) {
152d5ac70f0Sopenharmony_ci		c = channel + index;
153d5ac70f0Sopenharmony_ci		s = tplg_channel_name(c->id);
154d5ac70f0Sopenharmony_ci		if (s == NULL)
155d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, pfx, "\t%u", c->id);
156d5ac70f0Sopenharmony_ci		else
157d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, pfx, "\t%s", s);
158d5ac70f0Sopenharmony_ci		if (err >= 0)
159d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, NULL, " {\n");
160d5ac70f0Sopenharmony_ci		if (err >= 0)
161d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, pfx, "\t\treg %d\n", c->reg);
162d5ac70f0Sopenharmony_ci		if (err >= 0 && c->shift > 0)
163d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, pfx, "\t\tshift %u\n", c->shift);
164d5ac70f0Sopenharmony_ci		if (err >= 0)
165d5ac70f0Sopenharmony_ci			err = tplg_save_printf(dst, pfx, "\t}\n");
166d5ac70f0Sopenharmony_ci	}
167d5ac70f0Sopenharmony_ci	if (err >= 0)
168d5ac70f0Sopenharmony_ci		err = tplg_save_printf(dst, pfx, "}\n");
169d5ac70f0Sopenharmony_ci	return err;
170d5ac70f0Sopenharmony_ci}
171