mtk-afe-platform-driver.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * mtk-afe-platform-driver.c -- Mediatek afe platform driver
  4. *
  5. * Copyright (c) 2016 MediaTek Inc.
  6. * Author: Garlic Tseng <[email protected]>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/dma-mapping.h>
  10. #include <sound/soc.h>
  11. #include "mtk-afe-platform-driver.h"
  12. #include "mtk-base-afe.h"
  13. int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe)
  14. {
  15. struct mtk_base_afe_dai *dai;
  16. size_t num_dai_drivers = 0, dai_idx = 0;
  17. /* calcualte total dai driver size */
  18. list_for_each_entry(dai, &afe->sub_dais, list) {
  19. num_dai_drivers += dai->num_dai_drivers;
  20. }
  21. dev_info(afe->dev, "%s(), num of dai %zd\n", __func__, num_dai_drivers);
  22. /* combine sub_dais */
  23. afe->num_dai_drivers = num_dai_drivers;
  24. afe->dai_drivers = devm_kcalloc(afe->dev,
  25. num_dai_drivers,
  26. sizeof(struct snd_soc_dai_driver),
  27. GFP_KERNEL);
  28. if (!afe->dai_drivers)
  29. return -ENOMEM;
  30. list_for_each_entry(dai, &afe->sub_dais, list) {
  31. /* dai driver */
  32. memcpy(&afe->dai_drivers[dai_idx],
  33. dai->dai_drivers,
  34. dai->num_dai_drivers *
  35. sizeof(struct snd_soc_dai_driver));
  36. dai_idx += dai->num_dai_drivers;
  37. }
  38. return 0;
  39. }
  40. EXPORT_SYMBOL_GPL(mtk_afe_combine_sub_dai);
  41. int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)
  42. {
  43. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
  44. struct mtk_base_afe_dai *dai;
  45. list_for_each_entry(dai, &afe->sub_dais, list) {
  46. if (dai->controls)
  47. snd_soc_add_component_controls(component,
  48. dai->controls,
  49. dai->num_controls);
  50. if (dai->dapm_widgets)
  51. snd_soc_dapm_new_controls(&component->dapm,
  52. dai->dapm_widgets,
  53. dai->num_dapm_widgets);
  54. }
  55. /* add routes after all widgets are added */
  56. list_for_each_entry(dai, &afe->sub_dais, list) {
  57. if (dai->dapm_routes)
  58. snd_soc_dapm_add_routes(&component->dapm,
  59. dai->dapm_routes,
  60. dai->num_dapm_routes);
  61. }
  62. snd_soc_dapm_new_widgets(component->dapm.card);
  63. return 0;
  64. }
  65. EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);
  66. snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
  67. struct snd_pcm_substream *substream)
  68. {
  69. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  70. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
  71. struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id];
  72. const struct mtk_base_memif_data *memif_data = memif->data;
  73. struct regmap *regmap = afe->regmap;
  74. struct device *dev = afe->dev;
  75. int reg_ofs_base = memif_data->reg_ofs_base;
  76. int reg_ofs_cur = memif_data->reg_ofs_cur;
  77. unsigned int hw_ptr = 0, hw_base = 0;
  78. int ret, pcm_ptr_bytes;
  79. ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr);
  80. if (ret || hw_ptr == 0) {
  81. dev_err(dev, "%s hw_ptr err\n", __func__);
  82. pcm_ptr_bytes = 0;
  83. goto POINTER_RETURN_FRAMES;
  84. }
  85. ret = regmap_read(regmap, reg_ofs_base, &hw_base);
  86. if (ret || hw_base == 0) {
  87. dev_err(dev, "%s hw_ptr err\n", __func__);
  88. pcm_ptr_bytes = 0;
  89. goto POINTER_RETURN_FRAMES;
  90. }
  91. pcm_ptr_bytes = hw_ptr - hw_base;
  92. POINTER_RETURN_FRAMES:
  93. return bytes_to_frames(substream->runtime, pcm_ptr_bytes);
  94. }
  95. EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);
  96. int mtk_afe_pcm_new(struct snd_soc_component *component,
  97. struct snd_soc_pcm_runtime *rtd)
  98. {
  99. size_t size;
  100. struct snd_pcm *pcm = rtd->pcm;
  101. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
  102. size = afe->mtk_afe_hardware->buffer_bytes_max;
  103. snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
  104. afe->dev, size, size);
  105. return 0;
  106. }
  107. EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
  108. const struct snd_soc_component_driver mtk_afe_pcm_platform = {
  109. .name = AFE_PCM_NAME,
  110. .pointer = mtk_afe_pcm_pointer,
  111. .pcm_construct = mtk_afe_pcm_new,
  112. };
  113. EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform);
  114. MODULE_DESCRIPTION("Mediatek simple platform driver");
  115. MODULE_AUTHOR("Garlic Tseng <[email protected]>");
  116. MODULE_LICENSE("GPL v2");