hda-probes.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2019-2021 Intel Corporation. All rights reserved.
  7. //
  8. // Author: Cezary Rojewski <[email protected]>
  9. // Converted to SOF client:
  10. // Ranjani Sridharan <[email protected]>
  11. // Peter Ujfalusi <[email protected]>
  12. //
  13. #include <linux/module.h>
  14. #include <sound/hdaudio_ext.h>
  15. #include <sound/soc.h>
  16. #include "../sof-priv.h"
  17. #include "../sof-client-probes.h"
  18. #include "../sof-client.h"
  19. #include "hda.h"
  20. static inline struct hdac_ext_stream *
  21. hda_compr_get_stream(struct snd_compr_stream *cstream)
  22. {
  23. return cstream->runtime->private_data;
  24. }
  25. static int hda_probes_compr_startup(struct sof_client_dev *cdev,
  26. struct snd_compr_stream *cstream,
  27. struct snd_soc_dai *dai, u32 *stream_id)
  28. {
  29. struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
  30. struct hdac_ext_stream *hext_stream;
  31. hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
  32. if (!hext_stream)
  33. return -EBUSY;
  34. hdac_stream(hext_stream)->curr_pos = 0;
  35. hdac_stream(hext_stream)->cstream = cstream;
  36. cstream->runtime->private_data = hext_stream;
  37. *stream_id = hdac_stream(hext_stream)->stream_tag;
  38. return 0;
  39. }
  40. static int hda_probes_compr_shutdown(struct sof_client_dev *cdev,
  41. struct snd_compr_stream *cstream,
  42. struct snd_soc_dai *dai)
  43. {
  44. struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
  45. struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
  46. int ret;
  47. ret = hda_dsp_stream_put(sdev, cstream->direction,
  48. hdac_stream(hext_stream)->stream_tag);
  49. if (ret < 0) {
  50. dev_dbg(sdev->dev, "stream put failed: %d\n", ret);
  51. return ret;
  52. }
  53. hdac_stream(hext_stream)->cstream = NULL;
  54. cstream->runtime->private_data = NULL;
  55. return 0;
  56. }
  57. static int hda_probes_compr_set_params(struct sof_client_dev *cdev,
  58. struct snd_compr_stream *cstream,
  59. struct snd_compr_params *params,
  60. struct snd_soc_dai *dai)
  61. {
  62. struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
  63. struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
  64. struct hdac_stream *hstream = hdac_stream(hext_stream);
  65. struct snd_dma_buffer *dmab;
  66. u32 bits, rate;
  67. int bps, ret;
  68. dmab = cstream->runtime->dma_buffer_p;
  69. /* compr params do not store bit depth, default to S32_LE */
  70. bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE);
  71. if (bps < 0)
  72. return bps;
  73. bits = hda_dsp_get_bits(sdev, bps);
  74. rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate);
  75. hstream->format_val = rate | bits | (params->codec.ch_out - 1);
  76. hstream->bufsize = cstream->runtime->buffer_size;
  77. hstream->period_bytes = cstream->runtime->fragment_size;
  78. hstream->no_period_wakeup = 0;
  79. ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
  80. if (ret < 0) {
  81. dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
  82. return ret;
  83. }
  84. return 0;
  85. }
  86. static int hda_probes_compr_trigger(struct sof_client_dev *cdev,
  87. struct snd_compr_stream *cstream,
  88. int cmd, struct snd_soc_dai *dai)
  89. {
  90. struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
  91. struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
  92. return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
  93. }
  94. static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
  95. struct snd_compr_stream *cstream,
  96. struct snd_compr_tstamp *tstamp,
  97. struct snd_soc_dai *dai)
  98. {
  99. struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
  100. struct snd_soc_pcm_stream *pstream;
  101. pstream = &dai->driver->capture;
  102. tstamp->copied_total = hdac_stream(hext_stream)->curr_pos;
  103. tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates);
  104. return 0;
  105. }
  106. /* SOF client implementation */
  107. static const struct sof_probes_host_ops hda_probes_ops = {
  108. .startup = hda_probes_compr_startup,
  109. .shutdown = hda_probes_compr_shutdown,
  110. .set_params = hda_probes_compr_set_params,
  111. .trigger = hda_probes_compr_trigger,
  112. .pointer = hda_probes_compr_pointer,
  113. };
  114. int hda_probes_register(struct snd_sof_dev *sdev)
  115. {
  116. return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops,
  117. sizeof(hda_probes_ops));
  118. }
  119. void hda_probes_unregister(struct snd_sof_dev *sdev)
  120. {
  121. sof_client_dev_unregister(sdev, "hda-probes", 0);
  122. }
  123. MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);