Skip to content

Commit 3084d01

Browse files
ranj063ujfalusi
authored andcommitted
ASoC: SOF: ops: Add new platform-specific ops for compress
Add new ops in the struct snd_sof_ops for platform-specific ops for compresssed streams. Also, define and set them for the HDA platforms. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent 126116e commit 3084d01

6 files changed

Lines changed: 292 additions & 11 deletions

File tree

sound/soc/sof/intel/hda-common-ops.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ const struct snd_sof_dsp_ops sof_hda_common_ops = {
5757
.pcm_pointer = hda_dsp_pcm_pointer,
5858
.pcm_ack = hda_dsp_pcm_ack,
5959

60+
.compr_open = hda_dsp_compr_open,
61+
.compr_hw_params = hda_dsp_compr_hw_params,
62+
.compr_hw_free = hda_dsp_stream_compr_hw_free,
63+
.compr_close = hda_dsp_compr_close,
64+
.compr_trigger = hda_dsp_compr_trigger,
65+
.compr_pointer = hda_dsp_compr_pointer,
66+
.compr_get_dai_frame_counter = hda_dsp_compr_get_stream_llp,
67+
6068
.get_dai_frame_counter = hda_dsp_get_stream_llp,
6169
.get_host_byte_counter = hda_dsp_get_stream_ldp,
6270

sound/soc/sof/intel/hda-pcm.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,71 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
151151
}
152152
EXPORT_SYMBOL_NS(hda_dsp_pcm_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON");
153153

154+
int hda_dsp_compr_hw_params(struct snd_sof_dev *sdev,
155+
struct snd_compr_stream *cstream,
156+
struct snd_compr_params *params,
157+
struct snd_sof_platform_stream_params *platform_params)
158+
{
159+
struct hdac_stream *hstream = cstream->runtime->private_data;
160+
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
161+
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
162+
struct snd_dma_buffer *dmab;
163+
u32 bits, rate;
164+
int bps;
165+
int ret;
166+
167+
hstream->cstream = cstream;
168+
dmab = cstream->runtime->dma_buffer_p;
169+
170+
/* Use correct format based on the used codec */
171+
switch (params->codec.id) {
172+
case SND_AUDIOCODEC_PCM:
173+
bps = snd_pcm_format_physical_width(params->codec.format);
174+
break;
175+
case SND_AUDIOCODEC_VORBIS:
176+
bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S16_LE);
177+
break;
178+
case SND_AUDIOCODEC_FLAC:
179+
{
180+
struct snd_dec_flac *dec_flac = &params->codec.options.flac_d;
181+
182+
if (dec_flac->sample_size == 16)
183+
bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S16_LE);
184+
else
185+
bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE);
186+
break;
187+
}
188+
default:
189+
bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE);
190+
}
191+
192+
if (bps < 0)
193+
return bps;
194+
bits = hda_dsp_get_bits(sdev, bps);
195+
rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate);
196+
197+
hstream->format_val = rate | bits | (params->codec.ch_out - 1);
198+
hstream->bufsize = cstream->runtime->buffer_size;
199+
hstream->period_bytes = cstream->runtime->fragment_size;
200+
hstream->no_period_wakeup = false;
201+
202+
/* params is not used so pass NULL */
203+
dmab = cstream->runtime->dma_buffer_p;
204+
ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
205+
if (ret < 0) {
206+
dev_err(sdev->dev, "%s: hdac prepare failed: %d\n", __func__, ret);
207+
return ret;
208+
}
209+
210+
if (hda)
211+
platform_params->no_ipc_position = hda->no_ipc_position;
212+
213+
platform_params->stream_tag = hstream->stream_tag;
214+
215+
return 0;
216+
}
217+
EXPORT_SYMBOL_NS(hda_dsp_compr_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON");
218+
154219
/* update SPIB register with appl position */
155220
int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
156221
{
@@ -184,6 +249,16 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
184249
}
185250
EXPORT_SYMBOL_NS(hda_dsp_pcm_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
186251

252+
int hda_dsp_compr_trigger(struct snd_sof_dev *sdev,
253+
struct snd_compr_stream *cstream, int cmd)
254+
{
255+
struct hdac_stream *hstream = cstream->runtime->private_data;
256+
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
257+
258+
return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
259+
}
260+
EXPORT_SYMBOL_NS(hda_dsp_compr_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
261+
187262
snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
188263
struct snd_pcm_substream *substream)
189264
{
@@ -216,6 +291,20 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
216291
}
217292
EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON");
218293

294+
int hda_dsp_compr_pointer(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream,
295+
struct snd_compr_tstamp64 *tstamp)
296+
{
297+
struct hdac_stream *hstream = cstream->runtime->private_data;
298+
299+
/* hstream->curr_pos is updated when we receive the ioc */
300+
tstamp->copied_total += hstream->curr_pos;
301+
302+
tstamp->byte_offset = hda_dsp_stream_get_position(hstream, cstream->direction, true);
303+
304+
return 0;
305+
}
306+
EXPORT_SYMBOL_NS(hda_dsp_compr_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON");
307+
219308
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
220309
struct snd_pcm_substream *substream)
221310
{
@@ -332,6 +421,41 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
332421
}
333422
EXPORT_SYMBOL_NS(hda_dsp_pcm_open, "SND_SOC_SOF_INTEL_HDA_COMMON");
334423

424+
int hda_dsp_compr_open(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream)
425+
{
426+
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
427+
struct snd_soc_component *scomp = sdev->component;
428+
struct hdac_ext_stream *dsp_stream;
429+
struct snd_sof_pcm *spcm;
430+
int direction = cstream->direction;
431+
432+
spcm = snd_sof_find_spcm_dai(scomp, rtd);
433+
if (!spcm) {
434+
dev_err(sdev->dev, "%s: can't find PCM with DAI ID %d\n",
435+
__func__, rtd->dai_link->id);
436+
return -EINVAL;
437+
}
438+
439+
dsp_stream = hda_dsp_stream_get(sdev, direction, 0);
440+
if (!dsp_stream) {
441+
dev_err(sdev->dev, "%s: no stream available\n", __func__);
442+
return -ENODEV;
443+
}
444+
445+
/* binding compr stream to hda stream */
446+
cstream->runtime->private_data = &dsp_stream->hstream;
447+
448+
/*
449+
* Reset the llp cache values (they are used for LLP compensation in
450+
* case the counter is not reset)
451+
*/
452+
dsp_stream->pplcllpl = 0;
453+
dsp_stream->pplcllpu = 0;
454+
455+
return 0;
456+
}
457+
EXPORT_SYMBOL_NS(hda_dsp_compr_open, "SND_SOC_SOF_INTEL_HDA_COMMON");
458+
335459
int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
336460
struct snd_pcm_substream *substream)
337461
{
@@ -351,3 +475,20 @@ int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
351475
return 0;
352476
}
353477
EXPORT_SYMBOL_NS(hda_dsp_pcm_close, "SND_SOC_SOF_INTEL_HDA_COMMON");
478+
479+
int hda_dsp_compr_close(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream)
480+
{
481+
struct hdac_stream *hstream = cstream->runtime->private_data;
482+
int direction = cstream->direction;
483+
int ret;
484+
485+
ret = hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
486+
if (ret)
487+
return -ENODEV;
488+
489+
/* unbinding compress stream to hda stream */
490+
hstream->cstream = NULL;
491+
cstream->runtime->private_data = NULL;
492+
return 0;
493+
}
494+
EXPORT_SYMBOL_NS(hda_dsp_compr_close, "SND_SOC_SOF_INTEL_HDA_COMMON");

sound/soc/sof/intel/hda-stream.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -743,13 +743,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
743743
return ret;
744744
}
745745

746-
int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
747-
struct snd_pcm_substream *substream)
746+
static int _hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
747+
struct hdac_stream *hstream)
748748
{
749-
struct hdac_stream *hstream = substream->runtime->private_data;
750749
struct hdac_ext_stream *hext_stream = container_of(hstream,
751-
struct hdac_ext_stream,
752-
hstream);
750+
struct hdac_ext_stream,
751+
hstream);
753752
int ret;
754753

755754
ret = hda_dsp_stream_reset(sdev, hstream);
@@ -774,8 +773,21 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
774773

775774
return 0;
776775
}
776+
777+
int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
778+
struct snd_pcm_substream *substream)
779+
{
780+
return _hda_dsp_stream_hw_free(sdev, substream->runtime->private_data);
781+
}
777782
EXPORT_SYMBOL_NS(hda_dsp_stream_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
778783

784+
int hda_dsp_stream_compr_hw_free(struct snd_sof_dev *sdev,
785+
struct snd_compr_stream *cstream)
786+
{
787+
return _hda_dsp_stream_hw_free(sdev, cstream->runtime->private_data);
788+
}
789+
EXPORT_SYMBOL_NS(hda_dsp_stream_compr_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
790+
779791
bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
780792
{
781793
struct hdac_bus *bus = sof_to_bus(sdev);
@@ -1158,11 +1170,9 @@ EXPORT_SYMBOL_NS(hda_dsp_stream_get_position, "SND_SOC_SOF_INTEL_HDA_COMMON");
11581170
*
11591171
* Returns the raw Linear Link Position value
11601172
*/
1161-
u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
1162-
struct snd_soc_component *component,
1163-
struct snd_pcm_substream *substream)
1173+
static u64 hda_dsp_get_llp(struct snd_sof_dev *sdev,
1174+
struct snd_soc_pcm_runtime *rtd, int dir)
11641175
{
1165-
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
11661176
struct snd_soc_pcm_runtime *be_rtd = NULL;
11671177
struct hdac_ext_stream *hext_stream;
11681178
struct snd_soc_dai *cpu_dai;
@@ -1173,7 +1183,7 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
11731183
* The LLP needs to be read from the Link DMA used for this FE as it is
11741184
* allowed to use any combination of Link and Host channels
11751185
*/
1176-
for_each_dpcm_be(rtd, substream->stream, dpcm) {
1186+
for_each_dpcm_be(rtd, dir, dpcm) {
11771187
if (dpcm->fe != rtd)
11781188
continue;
11791189

@@ -1187,7 +1197,7 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
11871197
if (!cpu_dai)
11881198
return 0;
11891199

1190-
hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
1200+
hext_stream = snd_soc_dai_dma_data_get(cpu_dai, dir);
11911201
if (!hext_stream)
11921202
return 0;
11931203

@@ -1211,8 +1221,29 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
12111221

12121222
return merge_u64(llp_u, llp_l);
12131223
}
1224+
1225+
u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
1226+
struct snd_soc_component *component,
1227+
struct snd_pcm_substream *substream)
1228+
{
1229+
return hda_dsp_get_llp(sdev, snd_soc_substream_to_rtd(substream),
1230+
substream->stream);
1231+
}
12141232
EXPORT_SYMBOL_NS(hda_dsp_get_stream_llp, "SND_SOC_SOF_INTEL_HDA_COMMON");
12151233

1234+
/**
1235+
* hda_dsp_compr_get_stream_llp - Retrieve the LLP (Linear Link Position) of the stream
1236+
* @sdev: SOF device
1237+
* @cstream: Compress stream
1238+
*
1239+
* Returns the raw Linear Link Position value
1240+
*/
1241+
u64 hda_dsp_compr_get_stream_llp(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream)
1242+
{
1243+
return hda_dsp_get_llp(sdev, cstream->private_data, cstream->direction);
1244+
}
1245+
EXPORT_SYMBOL_NS(hda_dsp_compr_get_stream_llp, "SND_SOC_SOF_INTEL_HDA_COMMON");
1246+
12161247
/**
12171248
* hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
12181249
* @sdev: SOF device

sound/soc/sof/intel/hda.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,21 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
660660
struct snd_pcm_substream *substream);
661661
int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream);
662662

663+
int hda_dsp_compr_open(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream);
664+
int hda_dsp_compr_close(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream);
665+
int hda_dsp_compr_hw_params(struct snd_sof_dev *sdev,
666+
struct snd_compr_stream *cstream,
667+
struct snd_compr_params *params,
668+
struct snd_sof_platform_stream_params *platform_params);
669+
int hda_dsp_stream_compr_hw_free(struct snd_sof_dev *sdev,
670+
struct snd_compr_stream *cstream);
671+
int hda_dsp_compr_trigger(struct snd_sof_dev *sdev,
672+
struct snd_compr_stream *cstream, int cmd);
673+
int hda_dsp_compr_pointer(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream,
674+
struct snd_compr_tstamp64 *tstamp);
675+
u64 hda_dsp_compr_get_stream_llp(struct snd_sof_dev *sdev,
676+
struct snd_compr_stream *cstream);
677+
663678
/*
664679
* DSP Stream Operations.
665680
*/

sound/soc/sof/ops.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/interrupt.h>
1616
#include <linux/kernel.h>
1717
#include <linux/types.h>
18+
#include <sound/compress_driver.h>
1819
#include <sound/pcm.h>
1920
#include "sof-priv.h"
2021

@@ -448,6 +449,79 @@ snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
448449
return 0;
449450
}
450451

452+
static inline int
453+
snd_sof_compr_platform_open(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream)
454+
{
455+
if (sof_ops(sdev) && sof_ops(sdev)->compr_open)
456+
return sof_ops(sdev)->compr_open(sdev, cstream);
457+
458+
return 0;
459+
}
460+
461+
/* disconnect pcm substream to a host stream */
462+
static inline int
463+
snd_sof_compr_platform_close(struct snd_sof_dev *sdev, struct snd_compr_stream *cstream)
464+
{
465+
if (sof_ops(sdev) && sof_ops(sdev)->compr_close)
466+
return sof_ops(sdev)->compr_close(sdev, cstream);
467+
468+
return 0;
469+
}
470+
471+
/* host stream hw params */
472+
static inline int
473+
snd_sof_compr_platform_hw_params(struct snd_sof_dev *sdev,
474+
struct snd_compr_stream *cstream,
475+
struct snd_compr_params *params,
476+
struct snd_sof_platform_stream_params *platform_params)
477+
{
478+
if (sof_ops(sdev) && sof_ops(sdev)->compr_hw_params)
479+
return sof_ops(sdev)->compr_hw_params(sdev, cstream, params, platform_params);
480+
481+
return 0;
482+
}
483+
484+
static inline int
485+
snd_sof_compr_platform_hw_free(struct snd_sof_dev *sdev,
486+
struct snd_compr_stream *cstream)
487+
{
488+
if (sof_ops(sdev) && sof_ops(sdev)->compr_hw_free)
489+
return sof_ops(sdev)->compr_hw_free(sdev, cstream);
490+
491+
return 0;
492+
}
493+
494+
static inline int
495+
snd_sof_compr_platform_trigger(struct snd_sof_dev *sdev,
496+
struct snd_compr_stream *cstream, int cmd)
497+
{
498+
if (sof_ops(sdev) && sof_ops(sdev)->compr_trigger)
499+
return sof_ops(sdev)->compr_trigger(sdev, cstream, cmd);
500+
501+
return 0;
502+
}
503+
504+
static inline snd_pcm_uframes_t
505+
snd_sof_compr_platform_pointer(struct snd_sof_dev *sdev,
506+
struct snd_compr_stream *cstream,
507+
struct snd_compr_tstamp64 *tstamp)
508+
{
509+
if (sof_ops(sdev) && sof_ops(sdev)->compr_pointer)
510+
return sof_ops(sdev)->compr_pointer(sdev, cstream, tstamp);
511+
512+
return 0;
513+
}
514+
515+
static inline u64
516+
snd_sof_compr_get_dai_frame_counter(struct snd_sof_dev *sdev,
517+
struct snd_compr_stream *cstream)
518+
{
519+
if (sof_ops(sdev) && sof_ops(sdev)->compr_get_dai_frame_counter)
520+
return sof_ops(sdev)->compr_get_dai_frame_counter(sdev, cstream);
521+
522+
return 0;
523+
}
524+
451525
/* host stream hw free */
452526
static inline int
453527
snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,

0 commit comments

Comments
 (0)