pcm030-audio-fabric.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Phytec pcm030 driver for the PSC of the Freescale MPC52xx
  4. // configured as AC97 interface
  5. //
  6. // Copyright 2008 Jon Smirl, Digispeaker
  7. // Author: Jon Smirl <[email protected]>
  8. #include <linux/init.h>
  9. #include <linux/module.h>
  10. #include <linux/device.h>
  11. #include <linux/of_device.h>
  12. #include <linux/of_platform.h>
  13. #include <sound/soc.h>
  14. #include "mpc5200_dma.h"
  15. #define DRV_NAME "pcm030-audio-fabric"
  16. struct pcm030_audio_data {
  17. struct snd_soc_card *card;
  18. struct platform_device *codec_device;
  19. };
  20. SND_SOC_DAILINK_DEFS(analog,
  21. DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")),
  22. DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
  23. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  24. SND_SOC_DAILINK_DEFS(iec958,
  25. DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")),
  26. DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")),
  27. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  28. static struct snd_soc_dai_link pcm030_fabric_dai[] = {
  29. {
  30. .name = "AC97.0",
  31. .stream_name = "AC97 Analog",
  32. SND_SOC_DAILINK_REG(analog),
  33. },
  34. {
  35. .name = "AC97.1",
  36. .stream_name = "AC97 IEC958",
  37. SND_SOC_DAILINK_REG(iec958),
  38. },
  39. };
  40. static struct snd_soc_card pcm030_card = {
  41. .name = "pcm030",
  42. .owner = THIS_MODULE,
  43. .dai_link = pcm030_fabric_dai,
  44. .num_links = ARRAY_SIZE(pcm030_fabric_dai),
  45. };
  46. static int pcm030_fabric_probe(struct platform_device *op)
  47. {
  48. struct device_node *np = op->dev.of_node;
  49. struct device_node *platform_np;
  50. struct snd_soc_card *card = &pcm030_card;
  51. struct pcm030_audio_data *pdata;
  52. struct snd_soc_dai_link *dai_link;
  53. int ret;
  54. int i;
  55. if (!of_machine_is_compatible("phytec,pcm030"))
  56. return -ENODEV;
  57. pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data),
  58. GFP_KERNEL);
  59. if (!pdata)
  60. return -ENOMEM;
  61. card->dev = &op->dev;
  62. pdata->card = card;
  63. platform_np = of_parse_phandle(np, "asoc-platform", 0);
  64. if (!platform_np) {
  65. dev_err(&op->dev, "ac97 not registered\n");
  66. return -ENODEV;
  67. }
  68. for_each_card_prelinks(card, i, dai_link)
  69. dai_link->platforms->of_node = platform_np;
  70. ret = request_module("snd-soc-wm9712");
  71. if (ret)
  72. dev_err(&op->dev, "request_module returned: %d\n", ret);
  73. pdata->codec_device = platform_device_alloc("wm9712-codec", -1);
  74. if (!pdata->codec_device)
  75. dev_err(&op->dev, "platform_device_alloc() failed\n");
  76. ret = platform_device_add(pdata->codec_device);
  77. if (ret) {
  78. dev_err(&op->dev, "platform_device_add() failed: %d\n", ret);
  79. platform_device_put(pdata->codec_device);
  80. }
  81. ret = snd_soc_register_card(card);
  82. if (ret) {
  83. dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
  84. platform_device_unregister(pdata->codec_device);
  85. }
  86. platform_set_drvdata(op, pdata);
  87. return ret;
  88. }
  89. static int pcm030_fabric_remove(struct platform_device *op)
  90. {
  91. struct pcm030_audio_data *pdata = platform_get_drvdata(op);
  92. snd_soc_unregister_card(pdata->card);
  93. platform_device_unregister(pdata->codec_device);
  94. return 0;
  95. }
  96. static const struct of_device_id pcm030_audio_match[] = {
  97. { .compatible = "phytec,pcm030-audio-fabric", },
  98. {}
  99. };
  100. MODULE_DEVICE_TABLE(of, pcm030_audio_match);
  101. static struct platform_driver pcm030_fabric_driver = {
  102. .probe = pcm030_fabric_probe,
  103. .remove = pcm030_fabric_remove,
  104. .driver = {
  105. .name = DRV_NAME,
  106. .of_match_table = pcm030_audio_match,
  107. },
  108. };
  109. module_platform_driver(pcm030_fabric_driver);
  110. MODULE_AUTHOR("Jon Smirl <[email protected]>");
  111. MODULE_DESCRIPTION(DRV_NAME ": mpc5200 pcm030 fabric driver");
  112. MODULE_LICENSE("GPL");