audio-graph-card2-custom-sample.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // audio-graph-card2-custom-sample.c
  4. //
  5. // Copyright (C) 2020 Renesas Electronics Corp.
  6. // Copyright (C) 2020 Kuninori Morimoto <[email protected]>
  7. //
  8. #include <linux/module.h>
  9. #include <linux/of_gpio.h>
  10. #include <linux/platform_device.h>
  11. #include <sound/graph_card.h>
  12. /*
  13. * Custom driver can have own priv
  14. * which includes asoc_simple_priv.
  15. */
  16. struct custom_priv {
  17. struct asoc_simple_priv simple_priv;
  18. /* custom driver's own params */
  19. int custom_params;
  20. };
  21. /* You can get custom_priv from simple_priv */
  22. #define simple_to_custom(simple) container_of((simple), struct custom_priv, simple_priv)
  23. static int custom_card_probe(struct snd_soc_card *card)
  24. {
  25. struct asoc_simple_priv *simple_priv = snd_soc_card_get_drvdata(card);
  26. struct custom_priv *custom_priv = simple_to_custom(simple_priv);
  27. struct device *dev = simple_priv_to_dev(simple_priv);
  28. dev_info(dev, "custom probe\n");
  29. custom_priv->custom_params = 1;
  30. /* you can use generic probe function */
  31. return asoc_graph_card_probe(card);
  32. }
  33. static int custom_hook_pre(struct asoc_simple_priv *priv)
  34. {
  35. struct device *dev = simple_priv_to_dev(priv);
  36. /* You can custom before parsing */
  37. dev_info(dev, "hook : %s\n", __func__);
  38. return 0;
  39. }
  40. static int custom_hook_post(struct asoc_simple_priv *priv)
  41. {
  42. struct device *dev = simple_priv_to_dev(priv);
  43. struct snd_soc_card *card;
  44. /* You can custom after parsing */
  45. dev_info(dev, "hook : %s\n", __func__);
  46. /* overwrite .probe sample */
  47. card = simple_priv_to_card(priv);
  48. card->probe = custom_card_probe;
  49. return 0;
  50. }
  51. static int custom_normal(struct asoc_simple_priv *priv,
  52. struct device_node *lnk,
  53. struct link_info *li)
  54. {
  55. struct device *dev = simple_priv_to_dev(priv);
  56. /*
  57. * You can custom Normal parsing
  58. * before/affter audio_graph2_link_normal()
  59. */
  60. dev_info(dev, "hook : %s\n", __func__);
  61. return audio_graph2_link_normal(priv, lnk, li);
  62. }
  63. static int custom_dpcm(struct asoc_simple_priv *priv,
  64. struct device_node *lnk,
  65. struct link_info *li)
  66. {
  67. struct device *dev = simple_priv_to_dev(priv);
  68. /*
  69. * You can custom DPCM parsing
  70. * before/affter audio_graph2_link_dpcm()
  71. */
  72. dev_info(dev, "hook : %s\n", __func__);
  73. return audio_graph2_link_dpcm(priv, lnk, li);
  74. }
  75. static int custom_c2c(struct asoc_simple_priv *priv,
  76. struct device_node *lnk,
  77. struct link_info *li)
  78. {
  79. struct device *dev = simple_priv_to_dev(priv);
  80. /*
  81. * You can custom Codec2Codec parsing
  82. * before/affter audio_graph2_link_c2c()
  83. */
  84. dev_info(dev, "hook : %s\n", __func__);
  85. return audio_graph2_link_c2c(priv, lnk, li);
  86. }
  87. /*
  88. * audio-graph-card2 has many hooks for your customizing.
  89. */
  90. static struct graph2_custom_hooks custom_hooks = {
  91. .hook_pre = custom_hook_pre,
  92. .hook_post = custom_hook_post,
  93. .custom_normal = custom_normal,
  94. .custom_dpcm = custom_dpcm,
  95. .custom_c2c = custom_c2c,
  96. };
  97. static int custom_startup(struct snd_pcm_substream *substream)
  98. {
  99. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  100. struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
  101. struct device *dev = simple_priv_to_dev(priv);
  102. dev_info(dev, "custom startup\n");
  103. return asoc_simple_startup(substream);
  104. }
  105. /* You can use custom ops */
  106. static const struct snd_soc_ops custom_ops = {
  107. .startup = custom_startup,
  108. .shutdown = asoc_simple_shutdown,
  109. .hw_params = asoc_simple_hw_params,
  110. };
  111. static int custom_probe(struct platform_device *pdev)
  112. {
  113. struct custom_priv *custom_priv;
  114. struct asoc_simple_priv *simple_priv;
  115. struct device *dev = &pdev->dev;
  116. int ret;
  117. custom_priv = devm_kzalloc(dev, sizeof(*custom_priv), GFP_KERNEL);
  118. if (!custom_priv)
  119. return -ENOMEM;
  120. simple_priv = &custom_priv->simple_priv;
  121. simple_priv->ops = &custom_ops; /* customize dai_link ops */
  122. /* use audio-graph-card2 parsing with own custom hooks */
  123. ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks);
  124. if (ret < 0)
  125. return ret;
  126. /* customize more if needed */
  127. return 0;
  128. }
  129. static const struct of_device_id custom_of_match[] = {
  130. { .compatible = "audio-graph-card2-custom-sample", },
  131. {},
  132. };
  133. MODULE_DEVICE_TABLE(of, custom_of_match);
  134. static struct platform_driver custom_card = {
  135. .driver = {
  136. .name = "audio-graph-card2-custom-sample",
  137. .of_match_table = custom_of_match,
  138. },
  139. .probe = custom_probe,
  140. .remove = asoc_simple_remove,
  141. };
  142. module_platform_driver(custom_card);
  143. MODULE_ALIAS("platform:asoc-audio-graph-card2-custom-sample");
  144. MODULE_LICENSE("GPL v2");
  145. MODULE_DESCRIPTION("ASoC Audio Graph Card2 Custom Sample");
  146. MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");