soc-utils.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // soc-util.c -- ALSA SoC Audio Layer utility functions
  4. //
  5. // Copyright 2009 Wolfson Microelectronics PLC.
  6. //
  7. // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  8. // Liam Girdwood <lrg@slimlogic.co.uk>
  9. #include <linux/platform_device.h>
  10. #include <linux/export.h>
  11. #include <sound/core.h>
  12. #include <sound/pcm.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots)
  16. {
  17. return sample_size * channels * tdm_slots;
  18. }
  19. EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size);
  20. int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
  21. {
  22. int sample_size;
  23. sample_size = snd_pcm_format_width(params_format(params));
  24. if (sample_size < 0)
  25. return sample_size;
  26. return snd_soc_calc_frame_size(sample_size, params_channels(params),
  27. 1);
  28. }
  29. EXPORT_SYMBOL_GPL(snd_soc_params_to_frame_size);
  30. int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots)
  31. {
  32. return fs * snd_soc_calc_frame_size(sample_size, channels, tdm_slots);
  33. }
  34. EXPORT_SYMBOL_GPL(snd_soc_calc_bclk);
  35. int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
  36. {
  37. int ret;
  38. ret = snd_soc_params_to_frame_size(params);
  39. if (ret > 0)
  40. return ret * params_rate(params);
  41. else
  42. return ret;
  43. }
  44. EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
  45. int snd_soc_component_enable_pin(struct snd_soc_component *component,
  46. const char *pin)
  47. {
  48. struct snd_soc_dapm_context *dapm =
  49. snd_soc_component_get_dapm(component);
  50. char *full_name;
  51. int ret;
  52. if (!component->name_prefix)
  53. return snd_soc_dapm_enable_pin(dapm, pin);
  54. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  55. if (!full_name)
  56. return -ENOMEM;
  57. ret = snd_soc_dapm_enable_pin(dapm, full_name);
  58. kfree(full_name);
  59. return ret;
  60. }
  61. EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
  62. int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
  63. const char *pin)
  64. {
  65. struct snd_soc_dapm_context *dapm =
  66. snd_soc_component_get_dapm(component);
  67. char *full_name;
  68. int ret;
  69. if (!component->name_prefix)
  70. return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
  71. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  72. if (!full_name)
  73. return -ENOMEM;
  74. ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name);
  75. kfree(full_name);
  76. return ret;
  77. }
  78. EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
  79. int snd_soc_component_disable_pin(struct snd_soc_component *component,
  80. const char *pin)
  81. {
  82. struct snd_soc_dapm_context *dapm =
  83. snd_soc_component_get_dapm(component);
  84. char *full_name;
  85. int ret;
  86. if (!component->name_prefix)
  87. return snd_soc_dapm_disable_pin(dapm, pin);
  88. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  89. if (!full_name)
  90. return -ENOMEM;
  91. ret = snd_soc_dapm_disable_pin(dapm, full_name);
  92. kfree(full_name);
  93. return ret;
  94. }
  95. EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
  96. int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
  97. const char *pin)
  98. {
  99. struct snd_soc_dapm_context *dapm =
  100. snd_soc_component_get_dapm(component);
  101. char *full_name;
  102. int ret;
  103. if (!component->name_prefix)
  104. return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
  105. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  106. if (!full_name)
  107. return -ENOMEM;
  108. ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name);
  109. kfree(full_name);
  110. return ret;
  111. }
  112. EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
  113. int snd_soc_component_nc_pin(struct snd_soc_component *component,
  114. const char *pin)
  115. {
  116. struct snd_soc_dapm_context *dapm =
  117. snd_soc_component_get_dapm(component);
  118. char *full_name;
  119. int ret;
  120. if (!component->name_prefix)
  121. return snd_soc_dapm_nc_pin(dapm, pin);
  122. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  123. if (!full_name)
  124. return -ENOMEM;
  125. ret = snd_soc_dapm_nc_pin(dapm, full_name);
  126. kfree(full_name);
  127. return ret;
  128. }
  129. EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
  130. int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
  131. const char *pin)
  132. {
  133. struct snd_soc_dapm_context *dapm =
  134. snd_soc_component_get_dapm(component);
  135. char *full_name;
  136. int ret;
  137. if (!component->name_prefix)
  138. return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
  139. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  140. if (!full_name)
  141. return -ENOMEM;
  142. ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name);
  143. kfree(full_name);
  144. return ret;
  145. }
  146. EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
  147. int snd_soc_component_get_pin_status(struct snd_soc_component *component,
  148. const char *pin)
  149. {
  150. struct snd_soc_dapm_context *dapm =
  151. snd_soc_component_get_dapm(component);
  152. char *full_name;
  153. int ret;
  154. if (!component->name_prefix)
  155. return snd_soc_dapm_get_pin_status(dapm, pin);
  156. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  157. if (!full_name)
  158. return -ENOMEM;
  159. ret = snd_soc_dapm_get_pin_status(dapm, full_name);
  160. kfree(full_name);
  161. return ret;
  162. }
  163. EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
  164. int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
  165. const char *pin)
  166. {
  167. struct snd_soc_dapm_context *dapm =
  168. snd_soc_component_get_dapm(component);
  169. char *full_name;
  170. int ret;
  171. if (!component->name_prefix)
  172. return snd_soc_dapm_force_enable_pin(dapm, pin);
  173. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  174. if (!full_name)
  175. return -ENOMEM;
  176. ret = snd_soc_dapm_force_enable_pin(dapm, full_name);
  177. kfree(full_name);
  178. return ret;
  179. }
  180. EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
  181. int snd_soc_component_force_enable_pin_unlocked(
  182. struct snd_soc_component *component,
  183. const char *pin)
  184. {
  185. struct snd_soc_dapm_context *dapm =
  186. snd_soc_component_get_dapm(component);
  187. char *full_name;
  188. int ret;
  189. if (!component->name_prefix)
  190. return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
  191. full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  192. if (!full_name)
  193. return -ENOMEM;
  194. ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name);
  195. kfree(full_name);
  196. return ret;
  197. }
  198. EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
  199. static const struct snd_pcm_hardware dummy_dma_hardware = {
  200. /* Random values to keep userspace happy when checking constraints */
  201. .info = SNDRV_PCM_INFO_INTERLEAVED |
  202. SNDRV_PCM_INFO_BLOCK_TRANSFER,
  203. .buffer_bytes_max = 128*1024,
  204. .period_bytes_min = PAGE_SIZE,
  205. .period_bytes_max = PAGE_SIZE*2,
  206. .periods_min = 2,
  207. .periods_max = 128,
  208. };
  209. static int dummy_dma_open(struct snd_pcm_substream *substream)
  210. {
  211. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  212. /* BE's dont need dummy params */
  213. if (!rtd->dai_link->no_pcm)
  214. snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
  215. return 0;
  216. }
  217. static const struct snd_pcm_ops dummy_dma_ops = {
  218. .open = dummy_dma_open,
  219. .ioctl = snd_pcm_lib_ioctl,
  220. };
  221. static const struct snd_soc_component_driver dummy_platform = {
  222. .ops = &dummy_dma_ops,
  223. };
  224. static const struct snd_soc_component_driver dummy_codec = {
  225. .idle_bias_on = 1,
  226. .use_pmdown_time = 1,
  227. .endianness = 1,
  228. .non_legacy_dai_naming = 1,
  229. };
  230. #define STUB_RATES SNDRV_PCM_RATE_8000_192000
  231. #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
  232. SNDRV_PCM_FMTBIT_U8 | \
  233. SNDRV_PCM_FMTBIT_S16_LE | \
  234. SNDRV_PCM_FMTBIT_U16_LE | \
  235. SNDRV_PCM_FMTBIT_S24_LE | \
  236. SNDRV_PCM_FMTBIT_U24_LE | \
  237. SNDRV_PCM_FMTBIT_S32_LE | \
  238. SNDRV_PCM_FMTBIT_U32_LE | \
  239. SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
  240. /*
  241. * The dummy CODEC is only meant to be used in situations where there is no
  242. * actual hardware.
  243. *
  244. * If there is actual hardware even if it does not have a control bus
  245. * the hardware will still have constraints like supported samplerates, etc.
  246. * which should be modelled. And the data flow graph also should be modelled
  247. * using DAPM.
  248. */
  249. static struct snd_soc_dai_driver dummy_dai = {
  250. .name = "snd-soc-dummy-dai",
  251. .playback = {
  252. .stream_name = "Playback",
  253. .channels_min = 1,
  254. .channels_max = 384,
  255. .rates = STUB_RATES,
  256. .formats = STUB_FORMATS,
  257. },
  258. .capture = {
  259. .stream_name = "Capture",
  260. .channels_min = 1,
  261. .channels_max = 384,
  262. .rates = STUB_RATES,
  263. .formats = STUB_FORMATS,
  264. },
  265. };
  266. int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
  267. {
  268. if (dai->driver == &dummy_dai)
  269. return 1;
  270. return 0;
  271. }
  272. static int snd_soc_dummy_probe(struct platform_device *pdev)
  273. {
  274. int ret;
  275. ret = devm_snd_soc_register_component(&pdev->dev,
  276. &dummy_codec, &dummy_dai, 1);
  277. if (ret < 0)
  278. return ret;
  279. ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform,
  280. NULL, 0);
  281. return ret;
  282. }
  283. static struct platform_driver soc_dummy_driver = {
  284. .driver = {
  285. .name = "snd-soc-dummy",
  286. },
  287. .probe = snd_soc_dummy_probe,
  288. };
  289. static struct platform_device *soc_dummy_dev;
  290. int __init snd_soc_util_init(void)
  291. {
  292. int ret;
  293. soc_dummy_dev =
  294. platform_device_register_simple("snd-soc-dummy", -1, NULL, 0);
  295. if (IS_ERR(soc_dummy_dev))
  296. return PTR_ERR(soc_dummy_dev);
  297. ret = platform_driver_register(&soc_dummy_driver);
  298. if (ret != 0)
  299. platform_device_unregister(soc_dummy_dev);
  300. return ret;
  301. }
  302. void __exit snd_soc_util_exit(void)
  303. {
  304. platform_driver_unregister(&soc_dummy_driver);
  305. platform_device_unregister(soc_dummy_dev);
  306. }