1 /* 2 * ASoC simple sound card support 3 * 4 * Copyright (C) 2012 Renesas Solutions Corp. 5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 #include <linux/clk.h> 12 #include <linux/device.h> 13 #include <linux/gpio.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/of_gpio.h> 17 #include <linux/platform_device.h> 18 #include <linux/string.h> 19 #include <sound/jack.h> 20 #include <sound/simple_card.h> 21 #include <sound/soc-dai.h> 22 #include <sound/soc.h> 23 24 struct asoc_simple_jack { 25 struct snd_soc_jack jack; 26 struct snd_soc_jack_pin pin; 27 struct snd_soc_jack_gpio gpio; 28 }; 29 30 struct simple_card_data { 31 struct snd_soc_card snd_card; 32 struct simple_dai_props { 33 struct asoc_simple_dai cpu_dai; 34 struct asoc_simple_dai codec_dai; 35 unsigned int mclk_fs; 36 } *dai_props; 37 unsigned int mclk_fs; 38 struct asoc_simple_jack hp_jack; 39 struct asoc_simple_jack mic_jack; 40 struct snd_soc_dai_link *dai_link; 41 }; 42 43 #define simple_priv_to_card(priv) (&(priv)->snd_card) 44 #define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) 45 #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev) 46 #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i)) 47 48 #define DAI "sound-dai" 49 #define CELL "#sound-dai-cells" 50 #define PREFIX "simple-audio-card," 51 52 #define asoc_simple_card_init_hp(card, sjack, prefix)\ 53 asoc_simple_card_init_jack(card, sjack, 1, prefix) 54 #define asoc_simple_card_init_mic(card, sjack, prefix)\ 55 asoc_simple_card_init_jack(card, sjack, 0, prefix) 56 static int asoc_simple_card_init_jack(struct snd_soc_card *card, 57 struct asoc_simple_jack *sjack, 58 int is_hp, char *prefix) 59 { 60 struct device *dev = card->dev; 61 enum of_gpio_flags flags; 62 char prop[128]; 63 char *pin_name; 64 char *gpio_name; 65 int mask; 66 int det; 67 68 sjack->gpio.gpio = -ENOENT; 69 70 if (is_hp) { 71 snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix); 72 pin_name = "Headphones"; 73 gpio_name = "Headphone detection"; 74 mask = SND_JACK_HEADPHONE; 75 } else { 76 snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix); 77 pin_name = "Mic Jack"; 78 gpio_name = "Mic detection"; 79 mask = SND_JACK_MICROPHONE; 80 } 81 82 det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags); 83 if (det == -EPROBE_DEFER) 84 return -EPROBE_DEFER; 85 86 if (gpio_is_valid(det)) { 87 sjack->pin.pin = pin_name; 88 sjack->pin.mask = mask; 89 90 sjack->gpio.name = gpio_name; 91 sjack->gpio.report = mask; 92 sjack->gpio.gpio = det; 93 sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW); 94 sjack->gpio.debounce_time = 150; 95 96 snd_soc_card_jack_new(card, pin_name, mask, 97 &sjack->jack, 98 &sjack->pin, 1); 99 100 snd_soc_jack_add_gpios(&sjack->jack, 1, 101 &sjack->gpio); 102 } 103 104 return 0; 105 } 106 107 static void asoc_simple_card_remove_jack(struct asoc_simple_jack *sjack) 108 { 109 if (gpio_is_valid(sjack->gpio.gpio)) 110 snd_soc_jack_free_gpios(&sjack->jack, 1, &sjack->gpio); 111 } 112 113 static int asoc_simple_card_startup(struct snd_pcm_substream *substream) 114 { 115 struct snd_soc_pcm_runtime *rtd = substream->private_data; 116 struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); 117 struct simple_dai_props *dai_props = 118 simple_priv_to_props(priv, rtd->num); 119 int ret; 120 121 ret = clk_prepare_enable(dai_props->cpu_dai.clk); 122 if (ret) 123 return ret; 124 125 ret = clk_prepare_enable(dai_props->codec_dai.clk); 126 if (ret) 127 clk_disable_unprepare(dai_props->cpu_dai.clk); 128 129 return ret; 130 } 131 132 static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) 133 { 134 struct snd_soc_pcm_runtime *rtd = substream->private_data; 135 struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); 136 struct simple_dai_props *dai_props = 137 simple_priv_to_props(priv, rtd->num); 138 139 clk_disable_unprepare(dai_props->cpu_dai.clk); 140 141 clk_disable_unprepare(dai_props->codec_dai.clk); 142 } 143 144 static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, 145 struct snd_pcm_hw_params *params) 146 { 147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 148 struct snd_soc_dai *codec_dai = rtd->codec_dai; 149 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 150 struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); 151 struct simple_dai_props *dai_props = 152 simple_priv_to_props(priv, rtd->num); 153 unsigned int mclk, mclk_fs = 0; 154 int ret = 0; 155 156 if (priv->mclk_fs) 157 mclk_fs = priv->mclk_fs; 158 else if (dai_props->mclk_fs) 159 mclk_fs = dai_props->mclk_fs; 160 161 if (mclk_fs) { 162 mclk = params_rate(params) * mclk_fs; 163 ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 164 SND_SOC_CLOCK_IN); 165 if (ret && ret != -ENOTSUPP) 166 goto err; 167 168 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, 169 SND_SOC_CLOCK_OUT); 170 if (ret && ret != -ENOTSUPP) 171 goto err; 172 } 173 return 0; 174 err: 175 return ret; 176 } 177 178 static const struct snd_soc_ops asoc_simple_card_ops = { 179 .startup = asoc_simple_card_startup, 180 .shutdown = asoc_simple_card_shutdown, 181 .hw_params = asoc_simple_card_hw_params, 182 }; 183 184 static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) 185 { 186 struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); 187 struct snd_soc_dai *codec = rtd->codec_dai; 188 struct snd_soc_dai *cpu = rtd->cpu_dai; 189 struct simple_dai_props *dai_props = 190 simple_priv_to_props(priv, rtd->num); 191 int ret; 192 193 ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai); 194 if (ret < 0) 195 return ret; 196 197 ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai); 198 if (ret < 0) 199 return ret; 200 201 ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX); 202 if (ret < 0) 203 return ret; 204 205 ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX); 206 if (ret < 0) 207 return ret; 208 209 return 0; 210 } 211 212 static int asoc_simple_card_dai_link_of(struct device_node *node, 213 struct simple_card_data *priv, 214 int idx, 215 bool is_top_level_node) 216 { 217 struct device *dev = simple_priv_to_dev(priv); 218 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); 219 struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); 220 struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai; 221 struct asoc_simple_dai *codec_dai = &dai_props->codec_dai; 222 struct device_node *cpu = NULL; 223 struct device_node *plat = NULL; 224 struct device_node *codec = NULL; 225 char prop[128]; 226 char *prefix = ""; 227 int ret, single_cpu; 228 229 /* For single DAI link & old style of DT node */ 230 if (is_top_level_node) 231 prefix = PREFIX; 232 233 snprintf(prop, sizeof(prop), "%scpu", prefix); 234 cpu = of_get_child_by_name(node, prop); 235 236 snprintf(prop, sizeof(prop), "%splat", prefix); 237 plat = of_get_child_by_name(node, prop); 238 239 snprintf(prop, sizeof(prop), "%scodec", prefix); 240 codec = of_get_child_by_name(node, prop); 241 242 if (!cpu || !codec) { 243 ret = -EINVAL; 244 dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); 245 goto dai_link_of_err; 246 } 247 248 ret = asoc_simple_card_parse_daifmt(dev, node, codec, 249 prefix, &dai_link->dai_fmt); 250 if (ret < 0) 251 goto dai_link_of_err; 252 253 of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs); 254 255 ret = asoc_simple_card_parse_cpu(cpu, dai_link, 256 DAI, CELL, &single_cpu); 257 if (ret < 0) 258 goto dai_link_of_err; 259 260 ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL); 261 if (ret < 0) 262 goto dai_link_of_err; 263 264 ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL); 265 if (ret < 0) 266 goto dai_link_of_err; 267 268 ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask, 269 &cpu_dai->rx_slot_mask, 270 &cpu_dai->slots, 271 &cpu_dai->slot_width); 272 if (ret < 0) 273 goto dai_link_of_err; 274 275 ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask, 276 &codec_dai->rx_slot_mask, 277 &codec_dai->slots, 278 &codec_dai->slot_width); 279 if (ret < 0) 280 goto dai_link_of_err; 281 282 ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai); 283 if (ret < 0) 284 goto dai_link_of_err; 285 286 ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai); 287 if (ret < 0) 288 goto dai_link_of_err; 289 290 ret = asoc_simple_card_canonicalize_dailink(dai_link); 291 if (ret < 0) 292 goto dai_link_of_err; 293 294 ret = asoc_simple_card_set_dailink_name(dev, dai_link, 295 "%s-%s", 296 dai_link->cpu_dai_name, 297 dai_link->codec_dai_name); 298 if (ret < 0) 299 goto dai_link_of_err; 300 301 dai_link->ops = &asoc_simple_card_ops; 302 dai_link->init = asoc_simple_card_dai_init; 303 304 dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); 305 dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt); 306 dev_dbg(dev, "\tcpu : %s / %d\n", 307 dai_link->cpu_dai_name, 308 dai_props->cpu_dai.sysclk); 309 dev_dbg(dev, "\tcodec : %s / %d\n", 310 dai_link->codec_dai_name, 311 dai_props->codec_dai.sysclk); 312 313 asoc_simple_card_canonicalize_cpu(dai_link, single_cpu); 314 315 dai_link_of_err: 316 of_node_put(cpu); 317 of_node_put(codec); 318 319 return ret; 320 } 321 322 static int asoc_simple_card_parse_aux_devs(struct device_node *node, 323 struct simple_card_data *priv) 324 { 325 struct device *dev = simple_priv_to_dev(priv); 326 struct device_node *aux_node; 327 struct snd_soc_card *card = simple_priv_to_card(priv); 328 int i, n, len; 329 330 if (!of_find_property(node, PREFIX "aux-devs", &len)) 331 return 0; /* Ok to have no aux-devs */ 332 333 n = len / sizeof(__be32); 334 if (n <= 0) 335 return -EINVAL; 336 337 card->aux_dev = devm_kzalloc(dev, 338 n * sizeof(*card->aux_dev), GFP_KERNEL); 339 if (!card->aux_dev) 340 return -ENOMEM; 341 342 for (i = 0; i < n; i++) { 343 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); 344 if (!aux_node) 345 return -EINVAL; 346 card->aux_dev[i].codec_of_node = aux_node; 347 } 348 349 card->num_aux_devs = n; 350 return 0; 351 } 352 353 static int asoc_simple_card_parse_of(struct device_node *node, 354 struct simple_card_data *priv) 355 { 356 struct device *dev = simple_priv_to_dev(priv); 357 struct snd_soc_card *card = simple_priv_to_card(priv); 358 struct device_node *dai_link; 359 int ret; 360 361 if (!node) 362 return -EINVAL; 363 364 dai_link = of_get_child_by_name(node, PREFIX "dai-link"); 365 366 /* The off-codec widgets */ 367 if (of_property_read_bool(node, PREFIX "widgets")) { 368 ret = snd_soc_of_parse_audio_simple_widgets(card, 369 PREFIX "widgets"); 370 if (ret) 371 goto card_parse_end; 372 } 373 374 /* DAPM routes */ 375 if (of_property_read_bool(node, PREFIX "routing")) { 376 ret = snd_soc_of_parse_audio_routing(card, 377 PREFIX "routing"); 378 if (ret) 379 goto card_parse_end; 380 } 381 382 /* Factor to mclk, used in hw_params() */ 383 of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs); 384 385 /* Single/Muti DAI link(s) & New style of DT node */ 386 if (dai_link) { 387 struct device_node *np = NULL; 388 int i = 0; 389 390 for_each_child_of_node(node, np) { 391 dev_dbg(dev, "\tlink %d:\n", i); 392 ret = asoc_simple_card_dai_link_of(np, priv, 393 i, false); 394 if (ret < 0) { 395 of_node_put(np); 396 goto card_parse_end; 397 } 398 i++; 399 } 400 } else { 401 /* For single DAI link & old style of DT node */ 402 ret = asoc_simple_card_dai_link_of(node, priv, 0, true); 403 if (ret < 0) 404 goto card_parse_end; 405 } 406 407 ret = asoc_simple_card_parse_card_name(card, PREFIX); 408 if (ret < 0) 409 goto card_parse_end; 410 411 ret = asoc_simple_card_parse_aux_devs(node, priv); 412 413 card_parse_end: 414 of_node_put(dai_link); 415 416 return ret; 417 } 418 419 static int asoc_simple_card_probe(struct platform_device *pdev) 420 { 421 struct simple_card_data *priv; 422 struct snd_soc_dai_link *dai_link; 423 struct simple_dai_props *dai_props; 424 struct device *dev = &pdev->dev; 425 struct device_node *np = dev->of_node; 426 struct snd_soc_card *card; 427 int num, ret; 428 429 /* Get the number of DAI links */ 430 if (np && of_get_child_by_name(np, PREFIX "dai-link")) 431 num = of_get_child_count(np); 432 else 433 num = 1; 434 435 /* Allocate the private data and the DAI link array */ 436 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 437 if (!priv) 438 return -ENOMEM; 439 440 dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); 441 dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); 442 if (!dai_props || !dai_link) 443 return -ENOMEM; 444 445 priv->dai_props = dai_props; 446 priv->dai_link = dai_link; 447 448 /* Init snd_soc_card */ 449 card = simple_priv_to_card(priv); 450 card->owner = THIS_MODULE; 451 card->dev = dev; 452 card->dai_link = priv->dai_link; 453 card->num_links = num; 454 455 if (np && of_device_is_available(np)) { 456 457 ret = asoc_simple_card_parse_of(np, priv); 458 if (ret < 0) { 459 if (ret != -EPROBE_DEFER) 460 dev_err(dev, "parse error %d\n", ret); 461 goto err; 462 } 463 464 } else { 465 struct asoc_simple_card_info *cinfo; 466 467 cinfo = dev->platform_data; 468 if (!cinfo) { 469 dev_err(dev, "no info for asoc-simple-card\n"); 470 return -EINVAL; 471 } 472 473 if (!cinfo->name || 474 !cinfo->codec_dai.name || 475 !cinfo->codec || 476 !cinfo->platform || 477 !cinfo->cpu_dai.name) { 478 dev_err(dev, "insufficient asoc_simple_card_info settings\n"); 479 return -EINVAL; 480 } 481 482 card->name = (cinfo->card) ? cinfo->card : cinfo->name; 483 dai_link->name = cinfo->name; 484 dai_link->stream_name = cinfo->name; 485 dai_link->platform_name = cinfo->platform; 486 dai_link->codec_name = cinfo->codec; 487 dai_link->cpu_dai_name = cinfo->cpu_dai.name; 488 dai_link->codec_dai_name = cinfo->codec_dai.name; 489 dai_link->dai_fmt = cinfo->daifmt; 490 dai_link->init = asoc_simple_card_dai_init; 491 memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, 492 sizeof(priv->dai_props->cpu_dai)); 493 memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, 494 sizeof(priv->dai_props->codec_dai)); 495 } 496 497 snd_soc_card_set_drvdata(card, priv); 498 499 ret = devm_snd_soc_register_card(dev, card); 500 if (ret >= 0) 501 return ret; 502 err: 503 asoc_simple_card_clean_reference(card); 504 505 return ret; 506 } 507 508 static int asoc_simple_card_remove(struct platform_device *pdev) 509 { 510 struct snd_soc_card *card = platform_get_drvdata(pdev); 511 struct simple_card_data *priv = snd_soc_card_get_drvdata(card); 512 513 asoc_simple_card_remove_jack(&priv->hp_jack); 514 asoc_simple_card_remove_jack(&priv->mic_jack); 515 516 return asoc_simple_card_clean_reference(card); 517 } 518 519 static const struct of_device_id asoc_simple_of_match[] = { 520 { .compatible = "simple-audio-card", }, 521 {}, 522 }; 523 MODULE_DEVICE_TABLE(of, asoc_simple_of_match); 524 525 static struct platform_driver asoc_simple_card = { 526 .driver = { 527 .name = "asoc-simple-card", 528 .pm = &snd_soc_pm_ops, 529 .of_match_table = asoc_simple_of_match, 530 }, 531 .probe = asoc_simple_card_probe, 532 .remove = asoc_simple_card_remove, 533 }; 534 535 module_platform_driver(asoc_simple_card); 536 537 MODULE_ALIAS("platform:asoc-simple-card"); 538 MODULE_LICENSE("GPL v2"); 539 MODULE_DESCRIPTION("ASoC Simple Sound Card"); 540 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 541