diff options
author | Jyri Sarha <jsarha@ti.com> | 2014-03-24 06:15:25 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-04-23 08:14:27 -0400 |
commit | b3ca11ff59bc5842b01f13421a17e6d9a8936784 (patch) | |
tree | 5117417d0de1b3ef141ac92abb77c501a828ba09 /sound/soc/generic | |
parent | 389cb8348cf5ac4a702c71bf13673c4c8bf01e34 (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.c | 239 |
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 | ||
89 | static int | 89 | static int |
90 | asoc_simple_card_sub_parse_of(struct device_node *np, | 90 | asoc_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 | ||
154 | static int simple_card_cpu_codec_of(struct device_node *node, | 145 | static 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 | |||
267 | dai_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 | |||
286 | err: | ||
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 */ |