1f95b4152SPeter Ujfalusi // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2f95b4152SPeter Ujfalusi // 3f95b4152SPeter Ujfalusi // This file is provided under a dual BSD/GPLv2 license. When using or 4f95b4152SPeter Ujfalusi // redistributing this file, you may do so under either license. 5f95b4152SPeter Ujfalusi // 6*3dc0d709SPeter Ujfalusi // Copyright(c) 2019-2021 Intel Corporation. All rights reserved. 7f95b4152SPeter Ujfalusi // 8f95b4152SPeter Ujfalusi // Author: Cezary Rojewski <cezary.rojewski@intel.com> 9*3dc0d709SPeter Ujfalusi // Converted to SOF client: 10*3dc0d709SPeter Ujfalusi // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 11*3dc0d709SPeter Ujfalusi // Peter Ujfalusi <peter.ujfalusi@linux.intel.com> 12f95b4152SPeter Ujfalusi // 13f95b4152SPeter Ujfalusi 14*3dc0d709SPeter Ujfalusi #include <linux/module.h> 15f95b4152SPeter Ujfalusi #include <sound/hdaudio_ext.h> 16f95b4152SPeter Ujfalusi #include <sound/soc.h> 17f95b4152SPeter Ujfalusi #include "../sof-priv.h" 18*3dc0d709SPeter Ujfalusi #include "../sof-client-probes.h" 19*3dc0d709SPeter Ujfalusi #include "../sof-client.h" 20f95b4152SPeter Ujfalusi #include "hda.h" 21f95b4152SPeter Ujfalusi 22f95b4152SPeter Ujfalusi static inline struct hdac_ext_stream * 23f95b4152SPeter Ujfalusi hda_compr_get_stream(struct snd_compr_stream *cstream) 24f95b4152SPeter Ujfalusi { 25f95b4152SPeter Ujfalusi return cstream->runtime->private_data; 26f95b4152SPeter Ujfalusi } 27f95b4152SPeter Ujfalusi 28*3dc0d709SPeter Ujfalusi static int hda_probes_compr_assign(struct sof_client_dev *cdev, 29f95b4152SPeter Ujfalusi struct snd_compr_stream *cstream, 30*3dc0d709SPeter Ujfalusi struct snd_soc_dai *dai, u32 *stream_id) 31f95b4152SPeter Ujfalusi { 32*3dc0d709SPeter Ujfalusi struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 337d88b960SPierre-Louis Bossart struct hdac_ext_stream *hext_stream; 34f95b4152SPeter Ujfalusi 357d88b960SPierre-Louis Bossart hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0); 367d88b960SPierre-Louis Bossart if (!hext_stream) 37f95b4152SPeter Ujfalusi return -EBUSY; 38f95b4152SPeter Ujfalusi 397d88b960SPierre-Louis Bossart hdac_stream(hext_stream)->curr_pos = 0; 407d88b960SPierre-Louis Bossart hdac_stream(hext_stream)->cstream = cstream; 417d88b960SPierre-Louis Bossart cstream->runtime->private_data = hext_stream; 42f95b4152SPeter Ujfalusi 43*3dc0d709SPeter Ujfalusi *stream_id = hdac_stream(hext_stream)->stream_tag; 44*3dc0d709SPeter Ujfalusi 45*3dc0d709SPeter Ujfalusi return 0; 46f95b4152SPeter Ujfalusi } 47f95b4152SPeter Ujfalusi 48*3dc0d709SPeter Ujfalusi static int hda_probes_compr_free(struct sof_client_dev *cdev, 49f95b4152SPeter Ujfalusi struct snd_compr_stream *cstream, 50f95b4152SPeter Ujfalusi struct snd_soc_dai *dai) 51f95b4152SPeter Ujfalusi { 527d88b960SPierre-Louis Bossart struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); 53*3dc0d709SPeter Ujfalusi struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 54f95b4152SPeter Ujfalusi int ret; 55f95b4152SPeter Ujfalusi 56f95b4152SPeter Ujfalusi ret = hda_dsp_stream_put(sdev, cstream->direction, 577d88b960SPierre-Louis Bossart hdac_stream(hext_stream)->stream_tag); 58f95b4152SPeter Ujfalusi if (ret < 0) { 59f95b4152SPeter Ujfalusi dev_dbg(sdev->dev, "stream put failed: %d\n", ret); 60f95b4152SPeter Ujfalusi return ret; 61f95b4152SPeter Ujfalusi } 62f95b4152SPeter Ujfalusi 637d88b960SPierre-Louis Bossart hdac_stream(hext_stream)->cstream = NULL; 64f95b4152SPeter Ujfalusi cstream->runtime->private_data = NULL; 65f95b4152SPeter Ujfalusi 66f95b4152SPeter Ujfalusi return 0; 67f95b4152SPeter Ujfalusi } 68f95b4152SPeter Ujfalusi 69*3dc0d709SPeter Ujfalusi static int hda_probes_compr_set_params(struct sof_client_dev *cdev, 70f95b4152SPeter Ujfalusi struct snd_compr_stream *cstream, 71f95b4152SPeter Ujfalusi struct snd_compr_params *params, 72f95b4152SPeter Ujfalusi struct snd_soc_dai *dai) 73f95b4152SPeter Ujfalusi { 747d88b960SPierre-Louis Bossart struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); 75*3dc0d709SPeter Ujfalusi struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 767d88b960SPierre-Louis Bossart struct hdac_stream *hstream = hdac_stream(hext_stream); 77f95b4152SPeter Ujfalusi struct snd_dma_buffer *dmab; 78f95b4152SPeter Ujfalusi u32 bits, rate; 79f95b4152SPeter Ujfalusi int bps, ret; 80f95b4152SPeter Ujfalusi 81f95b4152SPeter Ujfalusi dmab = cstream->runtime->dma_buffer_p; 82f95b4152SPeter Ujfalusi /* compr params do not store bit depth, default to S32_LE */ 83f95b4152SPeter Ujfalusi bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE); 84f95b4152SPeter Ujfalusi if (bps < 0) 85f95b4152SPeter Ujfalusi return bps; 86f95b4152SPeter Ujfalusi bits = hda_dsp_get_bits(sdev, bps); 87f95b4152SPeter Ujfalusi rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate); 88f95b4152SPeter Ujfalusi 89f95b4152SPeter Ujfalusi hstream->format_val = rate | bits | (params->codec.ch_out - 1); 90f95b4152SPeter Ujfalusi hstream->bufsize = cstream->runtime->buffer_size; 91f95b4152SPeter Ujfalusi hstream->period_bytes = cstream->runtime->fragment_size; 92f95b4152SPeter Ujfalusi hstream->no_period_wakeup = 0; 93f95b4152SPeter Ujfalusi 947d88b960SPierre-Louis Bossart ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL); 95f95b4152SPeter Ujfalusi if (ret < 0) { 96f95b4152SPeter Ujfalusi dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); 97f95b4152SPeter Ujfalusi return ret; 98f95b4152SPeter Ujfalusi } 99f95b4152SPeter Ujfalusi 100f95b4152SPeter Ujfalusi return 0; 101f95b4152SPeter Ujfalusi } 102f95b4152SPeter Ujfalusi 103*3dc0d709SPeter Ujfalusi static int hda_probes_compr_trigger(struct sof_client_dev *cdev, 104*3dc0d709SPeter Ujfalusi struct snd_compr_stream *cstream, 105*3dc0d709SPeter Ujfalusi int cmd, struct snd_soc_dai *dai) 106f95b4152SPeter Ujfalusi { 1077d88b960SPierre-Louis Bossart struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); 108*3dc0d709SPeter Ujfalusi struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 109f95b4152SPeter Ujfalusi 1107d88b960SPierre-Louis Bossart return hda_dsp_stream_trigger(sdev, hext_stream, cmd); 111f95b4152SPeter Ujfalusi } 112f95b4152SPeter Ujfalusi 113*3dc0d709SPeter Ujfalusi static int hda_probes_compr_pointer(struct sof_client_dev *cdev, 114f95b4152SPeter Ujfalusi struct snd_compr_stream *cstream, 115f95b4152SPeter Ujfalusi struct snd_compr_tstamp *tstamp, 116f95b4152SPeter Ujfalusi struct snd_soc_dai *dai) 117f95b4152SPeter Ujfalusi { 1187d88b960SPierre-Louis Bossart struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); 119f95b4152SPeter Ujfalusi struct snd_soc_pcm_stream *pstream; 120f95b4152SPeter Ujfalusi 121f95b4152SPeter Ujfalusi pstream = &dai->driver->capture; 1227d88b960SPierre-Louis Bossart tstamp->copied_total = hdac_stream(hext_stream)->curr_pos; 123f95b4152SPeter Ujfalusi tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates); 124f95b4152SPeter Ujfalusi 125f95b4152SPeter Ujfalusi return 0; 126f95b4152SPeter Ujfalusi } 127*3dc0d709SPeter Ujfalusi 128*3dc0d709SPeter Ujfalusi /* SOF client implementation */ 129*3dc0d709SPeter Ujfalusi static const struct sof_probes_host_ops hda_probes_ops = { 130*3dc0d709SPeter Ujfalusi .assign = hda_probes_compr_assign, 131*3dc0d709SPeter Ujfalusi .free = hda_probes_compr_free, 132*3dc0d709SPeter Ujfalusi .set_params = hda_probes_compr_set_params, 133*3dc0d709SPeter Ujfalusi .trigger = hda_probes_compr_trigger, 134*3dc0d709SPeter Ujfalusi .pointer = hda_probes_compr_pointer, 135*3dc0d709SPeter Ujfalusi }; 136*3dc0d709SPeter Ujfalusi 137*3dc0d709SPeter Ujfalusi int hda_probes_register(struct snd_sof_dev *sdev) 138*3dc0d709SPeter Ujfalusi { 139*3dc0d709SPeter Ujfalusi return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops, 140*3dc0d709SPeter Ujfalusi sizeof(hda_probes_ops)); 141*3dc0d709SPeter Ujfalusi } 142*3dc0d709SPeter Ujfalusi 143*3dc0d709SPeter Ujfalusi void hda_probes_unregister(struct snd_sof_dev *sdev) 144*3dc0d709SPeter Ujfalusi { 145*3dc0d709SPeter Ujfalusi sof_client_dev_unregister(sdev, "hda-probes", 0); 146*3dc0d709SPeter Ujfalusi } 147*3dc0d709SPeter Ujfalusi 148*3dc0d709SPeter Ujfalusi MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); 149