dmic.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * dmic.c -- SoC audio for Generic Digital MICs
  4. *
  5. * Author: Liam Girdwood <[email protected]>
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/gpio.h>
  9. #include <linux/gpio/consumer.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/slab.h>
  12. #include <linux/module.h>
  13. #include <sound/core.h>
  14. #include <sound/pcm.h>
  15. #include <sound/soc.h>
  16. #include <sound/soc-dapm.h>
  17. #define MAX_MODESWITCH_DELAY 70
  18. static int modeswitch_delay;
  19. module_param(modeswitch_delay, uint, 0644);
  20. static int wakeup_delay;
  21. module_param(wakeup_delay, uint, 0644);
  22. struct dmic {
  23. struct gpio_desc *gpio_en;
  24. int wakeup_delay;
  25. /* Delay after DMIC mode switch */
  26. int modeswitch_delay;
  27. };
  28. static int dmic_daiops_trigger(struct snd_pcm_substream *substream,
  29. int cmd, struct snd_soc_dai *dai)
  30. {
  31. struct snd_soc_component *component = dai->component;
  32. struct dmic *dmic = snd_soc_component_get_drvdata(component);
  33. switch (cmd) {
  34. case SNDRV_PCM_TRIGGER_STOP:
  35. if (dmic->modeswitch_delay)
  36. mdelay(dmic->modeswitch_delay);
  37. break;
  38. }
  39. return 0;
  40. }
  41. static const struct snd_soc_dai_ops dmic_dai_ops = {
  42. .trigger = dmic_daiops_trigger,
  43. };
  44. static int dmic_aif_event(struct snd_soc_dapm_widget *w,
  45. struct snd_kcontrol *kcontrol, int event) {
  46. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  47. struct dmic *dmic = snd_soc_component_get_drvdata(component);
  48. switch (event) {
  49. case SND_SOC_DAPM_POST_PMU:
  50. if (dmic->gpio_en)
  51. gpiod_set_value_cansleep(dmic->gpio_en, 1);
  52. if (dmic->wakeup_delay)
  53. msleep(dmic->wakeup_delay);
  54. break;
  55. case SND_SOC_DAPM_POST_PMD:
  56. if (dmic->gpio_en)
  57. gpiod_set_value_cansleep(dmic->gpio_en, 0);
  58. break;
  59. }
  60. return 0;
  61. }
  62. static struct snd_soc_dai_driver dmic_dai = {
  63. .name = "dmic-hifi",
  64. .capture = {
  65. .stream_name = "Capture",
  66. .channels_min = 1,
  67. .channels_max = 8,
  68. .rates = SNDRV_PCM_RATE_CONTINUOUS,
  69. .formats = SNDRV_PCM_FMTBIT_S32_LE
  70. | SNDRV_PCM_FMTBIT_S24_LE
  71. | SNDRV_PCM_FMTBIT_S16_LE
  72. | SNDRV_PCM_FMTBIT_DSD_U8
  73. | SNDRV_PCM_FMTBIT_DSD_U16_LE
  74. | SNDRV_PCM_FMTBIT_DSD_U32_LE,
  75. },
  76. .ops = &dmic_dai_ops,
  77. };
  78. static int dmic_component_probe(struct snd_soc_component *component)
  79. {
  80. struct dmic *dmic;
  81. dmic = devm_kzalloc(component->dev, sizeof(*dmic), GFP_KERNEL);
  82. if (!dmic)
  83. return -ENOMEM;
  84. dmic->gpio_en = devm_gpiod_get_optional(component->dev,
  85. "dmicen", GPIOD_OUT_LOW);
  86. if (IS_ERR(dmic->gpio_en))
  87. return PTR_ERR(dmic->gpio_en);
  88. device_property_read_u32(component->dev, "wakeup-delay-ms",
  89. &dmic->wakeup_delay);
  90. device_property_read_u32(component->dev, "modeswitch-delay-ms",
  91. &dmic->modeswitch_delay);
  92. if (wakeup_delay)
  93. dmic->wakeup_delay = wakeup_delay;
  94. if (modeswitch_delay)
  95. dmic->modeswitch_delay = modeswitch_delay;
  96. if (dmic->modeswitch_delay > MAX_MODESWITCH_DELAY)
  97. dmic->modeswitch_delay = MAX_MODESWITCH_DELAY;
  98. snd_soc_component_set_drvdata(component, dmic);
  99. return 0;
  100. }
  101. static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
  102. SND_SOC_DAPM_AIF_OUT_E("DMIC AIF", "Capture", 0,
  103. SND_SOC_NOPM, 0, 0, dmic_aif_event,
  104. SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
  105. SND_SOC_DAPM_INPUT("DMic"),
  106. };
  107. static const struct snd_soc_dapm_route intercon[] = {
  108. {"DMIC AIF", NULL, "DMic"},
  109. };
  110. static const struct snd_soc_component_driver soc_dmic = {
  111. .probe = dmic_component_probe,
  112. .dapm_widgets = dmic_dapm_widgets,
  113. .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets),
  114. .dapm_routes = intercon,
  115. .num_dapm_routes = ARRAY_SIZE(intercon),
  116. .idle_bias_on = 1,
  117. .use_pmdown_time = 1,
  118. .endianness = 1,
  119. };
  120. static int dmic_dev_probe(struct platform_device *pdev)
  121. {
  122. int err;
  123. u32 chans;
  124. struct snd_soc_dai_driver *dai_drv = &dmic_dai;
  125. if (pdev->dev.of_node) {
  126. err = of_property_read_u32(pdev->dev.of_node, "num-channels", &chans);
  127. if (err && (err != -EINVAL))
  128. return err;
  129. if (!err) {
  130. if (chans < 1 || chans > 8)
  131. return -EINVAL;
  132. dai_drv = devm_kzalloc(&pdev->dev, sizeof(*dai_drv), GFP_KERNEL);
  133. if (!dai_drv)
  134. return -ENOMEM;
  135. memcpy(dai_drv, &dmic_dai, sizeof(*dai_drv));
  136. dai_drv->capture.channels_max = chans;
  137. }
  138. }
  139. return devm_snd_soc_register_component(&pdev->dev,
  140. &soc_dmic, dai_drv, 1);
  141. }
  142. MODULE_ALIAS("platform:dmic-codec");
  143. static const struct of_device_id dmic_dev_match[] = {
  144. {.compatible = "dmic-codec"},
  145. {}
  146. };
  147. MODULE_DEVICE_TABLE(of, dmic_dev_match);
  148. static struct platform_driver dmic_driver = {
  149. .driver = {
  150. .name = "dmic-codec",
  151. .of_match_table = dmic_dev_match,
  152. },
  153. .probe = dmic_dev_probe,
  154. };
  155. module_platform_driver(dmic_driver);
  156. MODULE_DESCRIPTION("Generic DMIC driver");
  157. MODULE_AUTHOR("Liam Girdwood <[email protected]>");
  158. MODULE_LICENSE("GPL");