0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <sound/hdaudio_ext.h>
0016 #include <sound/soc.h>
0017 #include "../sof-priv.h"
0018 #include "../sof-client-probes.h"
0019 #include "../sof-client.h"
0020 #include "hda.h"
0021
0022 static inline struct hdac_ext_stream *
0023 hda_compr_get_stream(struct snd_compr_stream *cstream)
0024 {
0025 return cstream->runtime->private_data;
0026 }
0027
0028 static int hda_probes_compr_startup(struct sof_client_dev *cdev,
0029 struct snd_compr_stream *cstream,
0030 struct snd_soc_dai *dai, u32 *stream_id)
0031 {
0032 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
0033 struct hdac_ext_stream *hext_stream;
0034
0035 hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
0036 if (!hext_stream)
0037 return -EBUSY;
0038
0039 hdac_stream(hext_stream)->curr_pos = 0;
0040 hdac_stream(hext_stream)->cstream = cstream;
0041 cstream->runtime->private_data = hext_stream;
0042
0043 *stream_id = hdac_stream(hext_stream)->stream_tag;
0044
0045 return 0;
0046 }
0047
0048 static int hda_probes_compr_shutdown(struct sof_client_dev *cdev,
0049 struct snd_compr_stream *cstream,
0050 struct snd_soc_dai *dai)
0051 {
0052 struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
0053 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
0054 int ret;
0055
0056 ret = hda_dsp_stream_put(sdev, cstream->direction,
0057 hdac_stream(hext_stream)->stream_tag);
0058 if (ret < 0) {
0059 dev_dbg(sdev->dev, "stream put failed: %d\n", ret);
0060 return ret;
0061 }
0062
0063 hdac_stream(hext_stream)->cstream = NULL;
0064 cstream->runtime->private_data = NULL;
0065
0066 return 0;
0067 }
0068
0069 static int hda_probes_compr_set_params(struct sof_client_dev *cdev,
0070 struct snd_compr_stream *cstream,
0071 struct snd_compr_params *params,
0072 struct snd_soc_dai *dai)
0073 {
0074 struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
0075 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
0076 struct hdac_stream *hstream = hdac_stream(hext_stream);
0077 struct snd_dma_buffer *dmab;
0078 u32 bits, rate;
0079 int bps, ret;
0080
0081 dmab = cstream->runtime->dma_buffer_p;
0082
0083 bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE);
0084 if (bps < 0)
0085 return bps;
0086 bits = hda_dsp_get_bits(sdev, bps);
0087 rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate);
0088
0089 hstream->format_val = rate | bits | (params->codec.ch_out - 1);
0090 hstream->bufsize = cstream->runtime->buffer_size;
0091 hstream->period_bytes = cstream->runtime->fragment_size;
0092 hstream->no_period_wakeup = 0;
0093
0094 ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
0095 if (ret < 0) {
0096 dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
0097 return ret;
0098 }
0099
0100 return 0;
0101 }
0102
0103 static int hda_probes_compr_trigger(struct sof_client_dev *cdev,
0104 struct snd_compr_stream *cstream,
0105 int cmd, struct snd_soc_dai *dai)
0106 {
0107 struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
0108 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
0109
0110 return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
0111 }
0112
0113 static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
0114 struct snd_compr_stream *cstream,
0115 struct snd_compr_tstamp *tstamp,
0116 struct snd_soc_dai *dai)
0117 {
0118 struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
0119 struct snd_soc_pcm_stream *pstream;
0120
0121 pstream = &dai->driver->capture;
0122 tstamp->copied_total = hdac_stream(hext_stream)->curr_pos;
0123 tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates);
0124
0125 return 0;
0126 }
0127
0128
0129 static const struct sof_probes_host_ops hda_probes_ops = {
0130 .startup = hda_probes_compr_startup,
0131 .shutdown = hda_probes_compr_shutdown,
0132 .set_params = hda_probes_compr_set_params,
0133 .trigger = hda_probes_compr_trigger,
0134 .pointer = hda_probes_compr_pointer,
0135 };
0136
0137 int hda_probes_register(struct snd_sof_dev *sdev)
0138 {
0139 return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops,
0140 sizeof(hda_probes_ops));
0141 }
0142
0143 void hda_probes_unregister(struct snd_sof_dev *sdev)
0144 {
0145 sof_client_dev_unregister(sdev, "hda-probes", 0);
0146 }
0147
0148 MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);