diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/simple-card.txt | 6 | ||||
-rw-r--r-- | sound/soc/codecs/sirf-audio-codec.c | 9 | ||||
-rw-r--r-- | sound/soc/generic/simple-card.c | 80 |
3 files changed, 62 insertions, 33 deletions
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index b30c222f9cd3..881914b139ca 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt | |||
@@ -43,6 +43,12 @@ Optional CPU/CODEC subnodes properties: | |||
43 | clock node (= common clock), or "system-clock-frequency" | 43 | clock node (= common clock), or "system-clock-frequency" |
44 | (if system doens't support common clock) | 44 | (if system doens't support common clock) |
45 | 45 | ||
46 | Note: | ||
47 | * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and | ||
48 | 'frame-inversion', the simple card will use the settings of CODEC for both | ||
49 | CPU and CODEC sides as we need to keep the settings identical for both ends | ||
50 | of the link. | ||
51 | |||
46 | Example: | 52 | Example: |
47 | 53 | ||
48 | sound { | 54 | sound { |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 90e3a228bae4..58e7c1f23771 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -337,18 +337,9 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = { | |||
337 | 337 | ||
338 | static int sirf_audio_codec_probe(struct snd_soc_codec *codec) | 338 | static int sirf_audio_codec_probe(struct snd_soc_codec *codec) |
339 | { | 339 | { |
340 | int ret; | ||
341 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 340 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
342 | struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); | ||
343 | 341 | ||
344 | pm_runtime_enable(codec->dev); | 342 | pm_runtime_enable(codec->dev); |
345 | codec->control_data = sirf_audio_codec->regmap; | ||
346 | |||
347 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
348 | if (ret != 0) { | ||
349 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
350 | return ret; | ||
351 | } | ||
352 | 343 | ||
353 | if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { | 344 | if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { |
354 | snd_soc_dapm_new_controls(dapm, | 345 | snd_soc_dapm_new_controls(dapm, |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 5dd47691ba41..2ee8ed56bcf1 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | struct simple_card_data { | 21 | struct simple_card_data { |
22 | struct snd_soc_card snd_card; | 22 | struct snd_soc_card snd_card; |
23 | unsigned int daifmt; | ||
24 | struct asoc_simple_dai cpu_dai; | 23 | struct asoc_simple_dai cpu_dai; |
25 | struct asoc_simple_dai codec_dai; | 24 | struct asoc_simple_dai codec_dai; |
26 | struct snd_soc_dai_link snd_link; | 25 | struct snd_soc_dai_link snd_link; |
@@ -105,12 +104,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
105 | /* get dai->name */ | 104 | /* get dai->name */ |
106 | ret = snd_soc_of_get_dai_name(np, name); | 105 | ret = snd_soc_of_get_dai_name(np, name); |
107 | if (ret < 0) | 106 | if (ret < 0) |
108 | goto parse_error; | 107 | return ret; |
109 | 108 | ||
110 | /* parse TDM slot */ | 109 | /* parse TDM slot */ |
111 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | 110 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); |
112 | if (ret) | 111 | if (ret) |
113 | goto parse_error; | 112 | return ret; |
114 | 113 | ||
115 | /* | 114 | /* |
116 | * bitclock-inversion, frame-inversion | 115 | * bitclock-inversion, frame-inversion |
@@ -130,7 +129,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
130 | clk = of_clk_get(np, 0); | 129 | clk = of_clk_get(np, 0); |
131 | if (IS_ERR(clk)) { | 130 | if (IS_ERR(clk)) { |
132 | ret = PTR_ERR(clk); | 131 | ret = PTR_ERR(clk); |
133 | goto parse_error; | 132 | return ret; |
134 | } | 133 | } |
135 | 134 | ||
136 | dai->sysclk = clk_get_rate(clk); | 135 | dai->sysclk = clk_get_rate(clk); |
@@ -144,12 +143,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
144 | dai->sysclk = clk_get_rate(clk); | 143 | dai->sysclk = clk_get_rate(clk); |
145 | } | 144 | } |
146 | 145 | ||
147 | ret = 0; | 146 | return 0; |
148 | |||
149 | parse_error: | ||
150 | of_node_put(node); | ||
151 | |||
152 | return ret; | ||
153 | } | 147 | } |
154 | 148 | ||
155 | static int asoc_simple_card_parse_of(struct device_node *node, | 149 | static int asoc_simple_card_parse_of(struct device_node *node, |
@@ -157,15 +151,18 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
157 | struct device *dev) | 151 | struct device *dev) |
158 | { | 152 | { |
159 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 153 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; |
154 | struct asoc_simple_dai *codec_dai = &priv->codec_dai; | ||
155 | struct asoc_simple_dai *cpu_dai = &priv->cpu_dai; | ||
160 | struct device_node *np; | 156 | struct device_node *np; |
161 | char *name; | 157 | char *name; |
158 | unsigned int daifmt; | ||
162 | int ret; | 159 | int ret; |
163 | 160 | ||
164 | /* parsing the card name from DT */ | 161 | /* parsing the card name from DT */ |
165 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); | 162 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); |
166 | 163 | ||
167 | /* get CPU/CODEC common format via simple-audio-card,format */ | 164 | /* get CPU/CODEC common format via simple-audio-card,format */ |
168 | priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & | 165 | daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & |
169 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); | 166 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); |
170 | 167 | ||
171 | /* off-codec widgets */ | 168 | /* off-codec widgets */ |
@@ -187,25 +184,35 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
187 | /* CPU sub-node */ | 184 | /* CPU sub-node */ |
188 | ret = -EINVAL; | 185 | ret = -EINVAL; |
189 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); | 186 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); |
190 | if (np) | 187 | if (np) { |
191 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, | 188 | ret = asoc_simple_card_sub_parse_of(np, daifmt, |
192 | &priv->cpu_dai, | 189 | cpu_dai, |
193 | &dai_link->cpu_of_node, | 190 | &dai_link->cpu_of_node, |
194 | &dai_link->cpu_dai_name); | 191 | &dai_link->cpu_dai_name); |
192 | of_node_put(np); | ||
193 | } | ||
195 | if (ret < 0) | 194 | if (ret < 0) |
196 | return ret; | 195 | return ret; |
197 | 196 | ||
198 | /* CODEC sub-node */ | 197 | /* CODEC sub-node */ |
199 | ret = -EINVAL; | 198 | ret = -EINVAL; |
200 | np = of_get_child_by_name(node, "simple-audio-card,codec"); | 199 | np = of_get_child_by_name(node, "simple-audio-card,codec"); |
201 | if (np) | 200 | if (np) { |
202 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, | 201 | ret = asoc_simple_card_sub_parse_of(np, daifmt, |
203 | &priv->codec_dai, | 202 | codec_dai, |
204 | &dai_link->codec_of_node, | 203 | &dai_link->codec_of_node, |
205 | &dai_link->codec_dai_name); | 204 | &dai_link->codec_dai_name); |
205 | of_node_put(np); | ||
206 | } | ||
206 | if (ret < 0) | 207 | if (ret < 0) |
207 | return ret; | 208 | return ret; |
208 | 209 | ||
210 | /* | ||
211 | * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC | ||
212 | * while the other bits should be identical unless buggy SW/HW design. | ||
213 | */ | ||
214 | cpu_dai->fmt = codec_dai->fmt; | ||
215 | |||
209 | if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) | 216 | if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) |
210 | return -EINVAL; | 217 | return -EINVAL; |
211 | 218 | ||
@@ -224,15 +231,15 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
224 | dai_link->platform_of_node = dai_link->cpu_of_node; | 231 | dai_link->platform_of_node = dai_link->cpu_of_node; |
225 | 232 | ||
226 | dev_dbg(dev, "card-name : %s\n", name); | 233 | dev_dbg(dev, "card-name : %s\n", name); |
227 | dev_dbg(dev, "platform : %04x\n", priv->daifmt); | 234 | dev_dbg(dev, "platform : %04x\n", daifmt); |
228 | dev_dbg(dev, "cpu : %s / %04x / %d\n", | 235 | dev_dbg(dev, "cpu : %s / %04x / %d\n", |
229 | dai_link->cpu_dai_name, | 236 | dai_link->cpu_dai_name, |
230 | priv->cpu_dai.fmt, | 237 | cpu_dai->fmt, |
231 | priv->cpu_dai.sysclk); | 238 | cpu_dai->sysclk); |
232 | dev_dbg(dev, "codec : %s / %04x / %d\n", | 239 | dev_dbg(dev, "codec : %s / %04x / %d\n", |
233 | dai_link->codec_dai_name, | 240 | dai_link->codec_dai_name, |
234 | priv->codec_dai.fmt, | 241 | codec_dai->fmt, |
235 | priv->codec_dai.sysclk); | 242 | codec_dai->sysclk); |
236 | 243 | ||
237 | /* | 244 | /* |
238 | * soc_bind_dai_link() will check cpu name | 245 | * soc_bind_dai_link() will check cpu name |
@@ -248,6 +255,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
248 | return 0; | 255 | return 0; |
249 | } | 256 | } |
250 | 257 | ||
258 | /* update the reference count of the devices nodes at end of probe */ | ||
259 | static int asoc_simple_card_unref(struct platform_device *pdev) | ||
260 | { | ||
261 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
262 | struct snd_soc_dai_link *dai_link; | ||
263 | struct device_node *np; | ||
264 | int num_links; | ||
265 | |||
266 | for (num_links = 0, dai_link = card->dai_link; | ||
267 | num_links < card->num_links; | ||
268 | num_links++, dai_link++) { | ||
269 | np = (struct device_node *) dai_link->cpu_of_node; | ||
270 | if (np) | ||
271 | of_node_put(np); | ||
272 | np = (struct device_node *) dai_link->codec_of_node; | ||
273 | if (np) | ||
274 | of_node_put(np); | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | |||
251 | static int asoc_simple_card_probe(struct platform_device *pdev) | 279 | static int asoc_simple_card_probe(struct platform_device *pdev) |
252 | { | 280 | { |
253 | struct simple_card_data *priv; | 281 | struct simple_card_data *priv; |
@@ -275,7 +303,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
275 | if (ret < 0) { | 303 | if (ret < 0) { |
276 | if (ret != -EPROBE_DEFER) | 304 | if (ret != -EPROBE_DEFER) |
277 | dev_err(dev, "parse error %d\n", ret); | 305 | dev_err(dev, "parse error %d\n", ret); |
278 | return ret; | 306 | goto err; |
279 | } | 307 | } |
280 | } else { | 308 | } else { |
281 | struct asoc_simple_card_info *cinfo; | 309 | struct asoc_simple_card_info *cinfo; |
@@ -318,7 +346,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
318 | 346 | ||
319 | snd_soc_card_set_drvdata(&priv->snd_card, priv); | 347 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
320 | 348 | ||
321 | return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); | 349 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
350 | |||
351 | err: | ||
352 | asoc_simple_card_unref(pdev); | ||
353 | return ret; | ||
322 | } | 354 | } |
323 | 355 | ||
324 | static const struct of_device_id asoc_simple_of_match[] = { | 356 | static const struct of_device_id asoc_simple_of_match[] = { |