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