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[] = { |
