acp-pcm.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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) 2021 Advanced Micro Devices, Inc.
  7. //
  8. // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
  9. /*
  10. * PCM interface for generic AMD audio ACP DSP block
  11. */
  12. #include <sound/pcm_params.h>
  13. #include "../ops.h"
  14. #include "acp.h"
  15. #include "acp-dsp-offset.h"
  16. int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
  17. struct snd_pcm_hw_params *params,
  18. struct snd_sof_platform_stream_params *platform_params)
  19. {
  20. struct snd_pcm_runtime *runtime = substream->runtime;
  21. struct acp_dsp_stream *stream = runtime->private_data;
  22. unsigned int buf_offset, index;
  23. u32 size;
  24. int ret;
  25. size = runtime->dma_bytes;
  26. stream->num_pages = PFN_UP(runtime->dma_bytes);
  27. stream->dmab = substream->runtime->dma_buffer_p;
  28. ret = acp_dsp_stream_config(sdev, stream);
  29. if (ret < 0) {
  30. dev_err(sdev->dev, "stream configuration failed\n");
  31. return ret;
  32. }
  33. platform_params->use_phy_address = true;
  34. platform_params->phy_addr = stream->reg_offset;
  35. platform_params->stream_tag = stream->stream_tag;
  36. platform_params->cont_update_posn = 1;
  37. /* write buffer size of stream in scratch memory */
  38. buf_offset = sdev->debug_box.offset +
  39. offsetof(struct scratch_reg_conf, buf_size);
  40. index = stream->stream_tag - 1;
  41. buf_offset = buf_offset + index * 4;
  42. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + buf_offset, size);
  43. return 0;
  44. }
  45. EXPORT_SYMBOL_NS(acp_pcm_hw_params, "SND_SOC_SOF_AMD_COMMON");
  46. int acp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
  47. {
  48. struct acp_dsp_stream *stream;
  49. stream = acp_dsp_stream_get(sdev, 0);
  50. if (!stream)
  51. return -ENODEV;
  52. substream->runtime->private_data = stream;
  53. stream->substream = substream;
  54. return 0;
  55. }
  56. EXPORT_SYMBOL_NS(acp_pcm_open, "SND_SOC_SOF_AMD_COMMON");
  57. int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
  58. {
  59. struct acp_dsp_stream *stream;
  60. stream = substream->runtime->private_data;
  61. if (!stream) {
  62. dev_err(sdev->dev, "No open stream\n");
  63. return -EINVAL;
  64. }
  65. stream->substream = NULL;
  66. substream->runtime->private_data = NULL;
  67. return acp_dsp_stream_put(sdev, stream);
  68. }
  69. EXPORT_SYMBOL_NS(acp_pcm_close, "SND_SOC_SOF_AMD_COMMON");
  70. snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev,
  71. struct snd_pcm_substream *substream)
  72. {
  73. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  74. struct snd_soc_component *scomp = sdev->component;
  75. struct snd_sof_pcm_stream *stream;
  76. struct sof_ipc_stream_posn posn;
  77. struct snd_sof_pcm *spcm;
  78. snd_pcm_uframes_t pos;
  79. int ret;
  80. spcm = snd_sof_find_spcm_dai(scomp, rtd);
  81. if (!spcm) {
  82. dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
  83. rtd->dai_link->id);
  84. return 0;
  85. }
  86. stream = &spcm->stream[substream->stream];
  87. ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
  88. if (ret < 0) {
  89. dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
  90. return 0;
  91. }
  92. memcpy(&stream->posn, &posn, sizeof(posn));
  93. pos = spcm->stream[substream->stream].posn.host_posn;
  94. pos = bytes_to_frames(substream->runtime, pos);
  95. return pos;
  96. }
  97. EXPORT_SYMBOL_NS(acp_pcm_pointer, "SND_SOC_SOF_AMD_COMMON");