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-2020 Intel Corporation. All rights reserved. 7 // 8 // Author: Cezary Rojewski <cezary.rojewski@intel.com> 9 // 10 11 #include <sound/hdaudio_ext.h> 12 #include <sound/soc.h> 13 #include "../sof-priv.h" 14 #include "hda.h" 15 16 static inline struct hdac_ext_stream * 17 hda_compr_get_stream(struct snd_compr_stream *cstream) 18 { 19 return cstream->runtime->private_data; 20 } 21 22 int hda_probe_compr_assign(struct snd_sof_dev *sdev, 23 struct snd_compr_stream *cstream, 24 struct snd_soc_dai *dai) 25 { 26 struct hdac_ext_stream *stream; 27 28 stream = hda_dsp_stream_get(sdev, cstream->direction, 0); 29 if (!stream) 30 return -EBUSY; 31 32 hdac_stream(stream)->curr_pos = 0; 33 hdac_stream(stream)->cstream = cstream; 34 cstream->runtime->private_data = stream; 35 36 return hdac_stream(stream)->stream_tag; 37 } 38 39 int hda_probe_compr_free(struct snd_sof_dev *sdev, 40 struct snd_compr_stream *cstream, 41 struct snd_soc_dai *dai) 42 { 43 struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); 44 int ret; 45 46 ret = hda_dsp_stream_put(sdev, cstream->direction, 47 hdac_stream(stream)->stream_tag); 48 if (ret < 0) { 49 dev_dbg(sdev->dev, "stream put failed: %d\n", ret); 50 return ret; 51 } 52 53 hdac_stream(stream)->cstream = NULL; 54 cstream->runtime->private_data = NULL; 55 56 return 0; 57 } 58 59 int hda_probe_compr_set_params(struct snd_sof_dev *sdev, 60 struct snd_compr_stream *cstream, 61 struct snd_compr_params *params, 62 struct snd_soc_dai *dai) 63 { 64 struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); 65 struct hdac_stream *hstream = hdac_stream(stream); 66 struct snd_dma_buffer *dmab; 67 u32 bits, rate; 68 int bps, ret; 69 70 dmab = cstream->runtime->dma_buffer_p; 71 /* compr params do not store bit depth, default to S32_LE */ 72 bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE); 73 if (bps < 0) 74 return bps; 75 bits = hda_dsp_get_bits(sdev, bps); 76 rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate); 77 78 hstream->format_val = rate | bits | (params->codec.ch_out - 1); 79 hstream->bufsize = cstream->runtime->buffer_size; 80 hstream->period_bytes = cstream->runtime->fragment_size; 81 hstream->no_period_wakeup = 0; 82 83 ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); 84 if (ret < 0) { 85 dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); 86 return ret; 87 } 88 89 return 0; 90 } 91 92 int hda_probe_compr_trigger(struct snd_sof_dev *sdev, 93 struct snd_compr_stream *cstream, int cmd, 94 struct snd_soc_dai *dai) 95 { 96 struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); 97 98 return hda_dsp_stream_trigger(sdev, stream, cmd); 99 } 100 101 int hda_probe_compr_pointer(struct snd_sof_dev *sdev, 102 struct snd_compr_stream *cstream, 103 struct snd_compr_tstamp *tstamp, 104 struct snd_soc_dai *dai) 105 { 106 struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); 107 struct snd_soc_pcm_stream *pstream; 108 109 pstream = &dai->driver->capture; 110 tstamp->copied_total = hdac_stream(stream)->curr_pos; 111 tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates); 112 113 return 0; 114 } 115