aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/generic
diff options
context:
space:
mode:
authorJyri Sarha <jsarha@ti.com>2014-03-24 06:15:25 -0400
committerMark Brown <broonie@linaro.org>2014-04-23 08:14:27 -0400
commitb3ca11ff59bc5842b01f13421a17e6d9a8936784 (patch)
tree5117417d0de1b3ef141ac92abb77c501a828ba09 /sound/soc/generic
parent389cb8348cf5ac4a702c71bf13673c4c8bf01e34 (diff)
ASoC: simple-card: Move dai-link level properties away from dai subnodes
The properties like format, bitclock-master, frame-master, bitclock-inversion, and frame-inversion should be common to the dais connected with a dai-link. For bitclock-master and frame-master properties to be unambiguous they need to indicate the mastering dai node with a phandle. Signed-off-by: Jyri Sarha <jsarha@ti.com> Acked-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/generic')
-rw-r--r--sound/soc/generic/simple-card.c239
1 files changed, 140 insertions, 99 deletions
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 835fd0258243..3f2e5807d7eb 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -88,7 +88,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
88 88
89static int 89static int
90asoc_simple_card_sub_parse_of(struct device_node *np, 90asoc_simple_card_sub_parse_of(struct device_node *np,
91 unsigned int daifmt,
92 struct asoc_simple_dai *dai, 91 struct asoc_simple_dai *dai,
93 const struct device_node **p_node, 92 const struct device_node **p_node,
94 const char **name) 93 const char **name)
@@ -117,14 +116,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
117 return ret; 116 return ret;
118 117
119 /* 118 /*
120 * bitclock-inversion, frame-inversion
121 * bitclock-master, frame-master
122 * and specific "format" if it has
123 */
124 dai->fmt = snd_soc_of_parse_daifmt(np, NULL, NULL, NULL);
125 dai->fmt |= daifmt;
126
127 /*
128 * dai->sysclk come from 119 * dai->sysclk come from
129 * "clocks = <&xxx>" (if system has common clock) 120 * "clocks = <&xxx>" (if system has common clock)
130 * or "system-clock-frequency = <xxx>" 121 * or "system-clock-frequency = <xxx>"
@@ -151,37 +142,135 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
151 return 0; 142 return 0;
152} 143}
153 144
154static int simple_card_cpu_codec_of(struct device_node *node, 145static int simple_card_dai_link_of(struct device_node *node,
155 int daifmt, 146 struct device *dev,
156 struct snd_soc_dai_link *dai_link, 147 struct snd_soc_dai_link *dai_link,
157 struct simple_dai_props *dai_props) 148 struct simple_dai_props *dai_props)
158{ 149{
159 struct device_node *np; 150 struct device_node *np = NULL;
151 struct device_node *bitclkmaster = NULL;
152 struct device_node *framemaster = NULL;
153 unsigned int daifmt;
154 char *name;
155 char prop[128];
156 char *prefix = "";
160 int ret; 157 int ret;
161 158
162 /* CPU sub-node */ 159 if (!strcmp("sound", node->name))
163 ret = -EINVAL; 160 prefix = "simple-audio-card,";
164 np = of_get_child_by_name(node, "simple-audio-card,cpu"); 161
165 if (np) { 162 daifmt = snd_soc_of_parse_daifmt(node, prefix,
166 ret = asoc_simple_card_sub_parse_of(np, daifmt, 163 &bitclkmaster, &framemaster);
167 &dai_props->cpu_dai, 164 daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
168 &dai_link->cpu_of_node, 165
169 &dai_link->cpu_dai_name); 166 snprintf(prop, sizeof(prop), "%scpu", prefix);
170 of_node_put(np); 167 np = of_get_child_by_name(node, prop);
168 if (!np) {
169 ret = -EINVAL;
170 dev_err(dev, "%s: Can't find simple-audio-card,cpu DT node\n",
171 __func__);
172 goto dai_link_of_err;
171 } 173 }
174
175 ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai,
176 &dai_link->cpu_of_node,
177 &dai_link->cpu_dai_name);
172 if (ret < 0) 178 if (ret < 0)
173 return ret; 179 goto dai_link_of_err;
180
181 dai_props->cpu_dai.fmt = daifmt;
182 switch (((np == bitclkmaster)<<4)|(np == framemaster)) {
183 case 0x11:
184 dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
185 break;
186 case 0x10:
187 dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
188 break;
189 case 0x01:
190 dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
191 break;
192 default:
193 dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
194 break;
195 }
174 196
175 /* CODEC sub-node */ 197 of_node_put(np);
176 ret = -EINVAL; 198 snprintf(prop, sizeof(prop), "%scodec", prefix);
177 np = of_get_child_by_name(node, "simple-audio-card,codec"); 199 np = of_get_child_by_name(node, prop);
178 if (np) { 200 if (!np) {
179 ret = asoc_simple_card_sub_parse_of(np, daifmt, 201 ret = -EINVAL;
180 &dai_props->codec_dai, 202 dev_err(dev, "%s: Can't find simple-audio-card,codec DT node\n",
181 &dai_link->codec_of_node, 203 __func__);
182 &dai_link->codec_dai_name); 204 goto dai_link_of_err;
183 of_node_put(np); 205 }
206
207 ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai,
208 &dai_link->codec_of_node,
209 &dai_link->codec_dai_name);
210 if (ret < 0)
211 goto dai_link_of_err;
212
213 if (strlen(prefix) && !bitclkmaster && !framemaster) {
214 /* No dai-link level and master setting was not found from
215 sound node level, revert back to legacy DT parsing and
216 take the settings from codec node. */
217 dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n",
218 __func__);
219 dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt =
220 snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) |
221 (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
222 } else {
223 dai_props->codec_dai.fmt = daifmt;
224 switch (((np == bitclkmaster)<<4)|(np == framemaster)) {
225 case 0x11:
226 dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
227 break;
228 case 0x10:
229 dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
230 break;
231 case 0x01:
232 dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
233 break;
234 default:
235 dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
236 break;
237 }
238 }
239
240 if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
241 ret = -EINVAL;
242 goto dai_link_of_err;
184 } 243 }
244
245 /* simple-card assumes platform == cpu */
246 dai_link->platform_of_node = dai_link->cpu_of_node;
247
248 /* Link name is created from CPU/CODEC dai name */
249 name = devm_kzalloc(dev,
250 strlen(dai_link->cpu_dai_name) +
251 strlen(dai_link->codec_dai_name) + 2,
252 GFP_KERNEL);
253 sprintf(name, "%s-%s", dai_link->cpu_dai_name,
254 dai_link->codec_dai_name);
255 dai_link->name = dai_link->stream_name = name;
256
257 dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
258 dev_dbg(dev, "\tcpu : %s / %04x / %d\n",
259 dai_link->cpu_dai_name,
260 dai_props->cpu_dai.fmt,
261 dai_props->cpu_dai.sysclk);
262 dev_dbg(dev, "\tcodec : %s / %04x / %d\n",
263 dai_link->codec_dai_name,
264 dai_props->codec_dai.fmt,
265 dai_props->codec_dai.sysclk);
266
267dai_link_of_err:
268 if (np)
269 of_node_put(np);
270 if (bitclkmaster)
271 of_node_put(bitclkmaster);
272 if (framemaster)
273 of_node_put(framemaster);
185 return ret; 274 return ret;
186} 275}
187 276
@@ -192,19 +281,11 @@ static int asoc_simple_card_parse_of(struct device_node *node,
192{ 281{
193 struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; 282 struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
194 struct simple_dai_props *dai_props = priv->dai_props; 283 struct simple_dai_props *dai_props = priv->dai_props;
195 struct device_node *np;
196 char *name;
197 unsigned int daifmt;
198 int ret; 284 int ret;
199 285
200 /* parsing the card name from DT */ 286 /* parsing the card name from DT */
201 snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); 287 snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name");
202 288
203 /* get CPU/CODEC common format via simple-audio-card,format */
204 daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,", NULL,
205 NULL) &
206 (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK);
207
208 /* off-codec widgets */ 289 /* off-codec widgets */
209 if (of_property_read_bool(node, "simple-audio-card,widgets")) { 290 if (of_property_read_bool(node, "simple-audio-card,widgets")) {
210 ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, 291 ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
@@ -221,71 +302,31 @@ static int asoc_simple_card_parse_of(struct device_node *node,
221 return ret; 302 return ret;
222 } 303 }
223 304
224 /* loop on the DAI links */ 305 dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ?
225 np = NULL; 306 priv->snd_card.name : "");
226 for (;;) { 307
227 if (multi) { 308 if (multi) {
228 np = of_get_next_child(node, np); 309 struct device_node *np = NULL;
229 if (!np) 310 int i;
230 break; 311 for (i = 0; (np = of_get_next_child(node, np)); i++) {
312 dev_dbg(dev, "\tlink %d:\n", i);
313 ret = simple_card_dai_link_of(np, dev, dai_link + i,
314 dai_props + i);
315 if (ret < 0) {
316 of_node_put(np);
317 return ret;
318 }
231 } 319 }
232 320 } else {
233 ret = simple_card_cpu_codec_of(multi ? np : node, 321 ret = simple_card_dai_link_of(node, dev, dai_link, dai_props);
234 daifmt, dai_link, dai_props);
235 if (ret < 0) 322 if (ret < 0)
236 goto err; 323 return ret;
237
238 /*
239 * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC
240 * while the other bits should be identical unless buggy SW/HW design.
241 */
242 dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt;
243
244 if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
245 ret = -EINVAL;
246 goto err;
247 }
248
249 /* simple-card assumes platform == cpu */
250 dai_link->platform_of_node = dai_link->cpu_of_node;
251
252 name = devm_kzalloc(dev,
253 strlen(dai_link->cpu_dai_name) +
254 strlen(dai_link->codec_dai_name) + 2,
255 GFP_KERNEL);
256 sprintf(name, "%s-%s", dai_link->cpu_dai_name,
257 dai_link->codec_dai_name);
258 dai_link->name = dai_link->stream_name = name;
259
260 if (!multi)
261 break;
262
263 dai_link++;
264 dai_props++;
265 } 324 }
266 325
267 /* card name is created from CPU/CODEC dai name */
268 dai_link = priv->snd_card.dai_link;
269 if (!priv->snd_card.name) 326 if (!priv->snd_card.name)
270 priv->snd_card.name = dai_link->name; 327 priv->snd_card.name = priv->snd_card.dai_link->name;
271
272 dev_dbg(dev, "card-name : %s\n", priv->snd_card.name);
273 dev_dbg(dev, "platform : %04x\n", daifmt);
274 dai_props = priv->dai_props;
275 dev_dbg(dev, "cpu : %s / %04x / %d\n",
276 dai_link->cpu_dai_name,
277 dai_props->cpu_dai.fmt,
278 dai_props->cpu_dai.sysclk);
279 dev_dbg(dev, "codec : %s / %04x / %d\n",
280 dai_link->codec_dai_name,
281 dai_props->codec_dai.fmt,
282 dai_props->codec_dai.sysclk);
283 328
284 return 0; 329 return 0;
285
286err:
287 of_node_put(np);
288 return ret;
289} 330}
290 331
291/* update the reference count of the devices nodes at end of probe */ 332/* update the reference count of the devices nodes at end of probe */