Skip to content

Commit 9113737

Browse files
committed
ASoC: SOF: Intel: add hda_dma_prepare/cleanup helpers
SoundWire BPT stream needs to use link and host DMAs. Thus we need helpers to prepare and cleanup the link and host DMAs. Currently the SoundWire BPT stream uses hda_cl_prepare/cleanup helpers. It works fine because we assume the SwoundWire BPT will not run with audio streams simultaneously. The new helpers are copied from hda_cl_prepare/cleanup and add a flag to reserve the paired host and link DMAs. The new helpers will be used by both code loader and SoundWire BPT. Signed-off-by: Bard Liao <[email protected]>
1 parent 6b85309 commit 9113737

File tree

3 files changed

+127
-91
lines changed

3 files changed

+127
-91
lines changed

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

Lines changed: 3 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -53,65 +53,8 @@ hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size,
5353
struct snd_dma_buffer *dmab, bool persistent_buffer, int direction,
5454
bool is_iccmax)
5555
{
56-
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
57-
struct hdac_ext_stream *hext_stream;
58-
struct hdac_stream *hstream;
59-
int ret;
60-
61-
hext_stream = hda_dsp_stream_get(sdev, direction, 0);
62-
63-
if (!hext_stream) {
64-
dev_err(sdev->dev, "error: no stream available\n");
65-
return ERR_PTR(-ENODEV);
66-
}
67-
hstream = &hext_stream->hstream;
68-
hstream->substream = NULL;
69-
70-
/*
71-
* Allocate DMA buffer if it is temporary or if the buffer is intended
72-
* to be persistent but not yet allocated.
73-
* We cannot rely solely on !dmab->area as caller might use a struct on
74-
* stack (when it is temporary) without clearing it to 0.
75-
*/
76-
if (!persistent_buffer || !dmab->area) {
77-
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
78-
if (ret < 0) {
79-
dev_err(sdev->dev, "%s: memory alloc failed: %d\n",
80-
__func__, ret);
81-
goto out_put;
82-
}
83-
}
84-
85-
hstream->period_bytes = 0;/* initialize period_bytes */
86-
hstream->format_val = format;
87-
hstream->bufsize = size;
88-
89-
if (is_iccmax) {
90-
ret = hda_dsp_iccmax_stream_hw_params(sdev, hext_stream, dmab, NULL);
91-
if (ret < 0) {
92-
dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
93-
goto out_free;
94-
}
95-
} else {
96-
ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
97-
if (ret < 0) {
98-
dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
99-
goto out_free;
100-
}
101-
hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_ENABLE, size);
102-
}
103-
104-
return hext_stream;
105-
106-
out_free:
107-
snd_dma_free_pages(dmab);
108-
dmab->area = NULL;
109-
dmab->bytes = 0;
110-
hstream->bufsize = 0;
111-
hstream->format_val = 0;
112-
out_put:
113-
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
114-
return ERR_PTR(ret);
56+
return hda_data_stream_prepare(dev, format, size, dmab, persistent_buffer,
57+
direction, is_iccmax, false);
11558
}
11659
EXPORT_SYMBOL_NS(hda_cl_prepare, "SND_SOC_SOF_INTEL_HDA_COMMON");
11760

@@ -275,38 +218,7 @@ EXPORT_SYMBOL_NS(hda_cl_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
275218
int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
276219
bool persistent_buffer, struct hdac_ext_stream *hext_stream)
277220
{
278-
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
279-
struct hdac_stream *hstream = &hext_stream->hstream;
280-
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
281-
int ret = 0;
282-
283-
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
284-
ret = hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0);
285-
else
286-
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
287-
SOF_HDA_SD_CTL_DMA_START, 0);
288-
289-
hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
290-
hstream->running = 0;
291-
hstream->substream = NULL;
292-
293-
/* reset BDL address */
294-
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
295-
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL, 0);
296-
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
297-
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);
298-
299-
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0);
300-
301-
if (!persistent_buffer) {
302-
snd_dma_free_pages(dmab);
303-
dmab->area = NULL;
304-
dmab->bytes = 0;
305-
hstream->bufsize = 0;
306-
hstream->format_val = 0;
307-
}
308-
309-
return ret;
221+
return hda_data_stream_cleanup(dev, dmab, persistent_buffer, hext_stream, false);
310222
}
311223
EXPORT_SYMBOL_NS(hda_cl_cleanup, "SND_SOC_SOF_INTEL_HDA_COMMON");
312224

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

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,3 +1243,119 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
12431243
return ((u64)ldp_u << 32) | ldp_l;
12441244
}
12451245
EXPORT_SYMBOL_NS(hda_dsp_get_stream_ldp, "SND_SOC_SOF_INTEL_HDA_COMMON");
1246+
1247+
struct hdac_ext_stream *
1248+
hda_data_stream_prepare(struct device *dev, unsigned int format, unsigned int size,
1249+
struct snd_dma_buffer *dmab, bool persistent_buffer, int direction,
1250+
bool is_iccmax, bool pair)
1251+
{
1252+
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
1253+
struct hdac_ext_stream *hext_stream;
1254+
struct hdac_stream *hstream;
1255+
int ret;
1256+
1257+
if (pair)
1258+
hext_stream = hda_dsp_stream_pair_get(sdev, direction, 0);
1259+
else
1260+
hext_stream = hda_dsp_stream_get(sdev, direction, 0);
1261+
1262+
if (!hext_stream) {
1263+
dev_err(sdev->dev, "%s: no stream available\n", __func__);
1264+
return ERR_PTR(-ENODEV);
1265+
}
1266+
hstream = &hext_stream->hstream;
1267+
hstream->substream = NULL;
1268+
1269+
/*
1270+
* Allocate DMA buffer if it is temporary or if the buffer is intended
1271+
* to be persistent but not yet allocated.
1272+
* We cannot rely solely on !dmab->area as caller might use a struct on
1273+
* stack (when it is temporary) without clearing it to 0.
1274+
*/
1275+
if (!persistent_buffer || !dmab->area) {
1276+
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
1277+
if (ret < 0) {
1278+
dev_err(sdev->dev, "%s: memory alloc failed: %d\n",
1279+
__func__, ret);
1280+
goto out_put;
1281+
}
1282+
}
1283+
1284+
hstream->period_bytes = 0; /* initialize period_bytes */
1285+
hstream->format_val = format;
1286+
hstream->bufsize = size;
1287+
1288+
if (is_iccmax) {
1289+
ret = hda_dsp_iccmax_stream_hw_params(sdev, hext_stream, dmab, NULL);
1290+
if (ret < 0) {
1291+
dev_err(sdev->dev, "%s: iccmax stream prepare failed: %d\n",
1292+
__func__, ret);
1293+
goto out_free;
1294+
}
1295+
} else {
1296+
ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
1297+
if (ret < 0) {
1298+
dev_err(sdev->dev, "%s: hdac prepare failed: %d\n", __func__, ret);
1299+
goto out_free;
1300+
}
1301+
hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_ENABLE, size);
1302+
}
1303+
1304+
return hext_stream;
1305+
1306+
out_free:
1307+
snd_dma_free_pages(dmab);
1308+
dmab->area = NULL;
1309+
dmab->bytes = 0;
1310+
hstream->bufsize = 0;
1311+
hstream->format_val = 0;
1312+
out_put:
1313+
if (pair)
1314+
hda_dsp_stream_pair_put(sdev, direction, hstream->stream_tag);
1315+
else
1316+
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
1317+
return ERR_PTR(ret);
1318+
}
1319+
EXPORT_SYMBOL_NS(hda_data_stream_prepare, "SND_SOC_SOF_INTEL_HDA_COMMON");
1320+
1321+
int hda_data_stream_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
1322+
bool persistent_buffer, struct hdac_ext_stream *hext_stream, bool pair)
1323+
{
1324+
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
1325+
struct hdac_stream *hstream = hdac_stream(hext_stream);
1326+
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
1327+
int ret = 0;
1328+
1329+
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
1330+
ret = hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0);
1331+
else
1332+
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
1333+
SOF_HDA_SD_CTL_DMA_START, 0);
1334+
1335+
if (pair)
1336+
hda_dsp_stream_pair_put(sdev, hstream->direction, hstream->stream_tag);
1337+
else
1338+
hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
1339+
1340+
hstream->running = 0;
1341+
hstream->substream = NULL;
1342+
1343+
/* reset BDL address */
1344+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
1345+
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL, 0);
1346+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
1347+
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);
1348+
1349+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0);
1350+
1351+
if (!persistent_buffer) {
1352+
snd_dma_free_pages(dmab);
1353+
dmab->area = NULL;
1354+
dmab->bytes = 0;
1355+
hstream->bufsize = 0;
1356+
hstream->format_val = 0;
1357+
}
1358+
1359+
return ret;
1360+
}
1361+
EXPORT_SYMBOL_NS(hda_data_stream_cleanup, "SND_SOC_SOF_INTEL_HDA_COMMON");

sound/soc/sof/intel/hda.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,14 @@ int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
905905
int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd,
906906
struct snd_soc_dai *cpu_dai);
907907

908+
struct hdac_ext_stream *
909+
hda_data_stream_prepare(struct device *dev, unsigned int format, unsigned int size,
910+
struct snd_dma_buffer *dmab, bool persistent_buffer, int direction,
911+
bool is_iccmax, bool pair);
912+
913+
int hda_data_stream_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
914+
bool persistent_buffer, struct hdac_ext_stream *hext_stream, bool pair);
915+
908916
/* common dai driver */
909917
extern struct snd_soc_dai_driver skl_dai[];
910918
int hda_dsp_dais_suspend(struct snd_sof_dev *sdev);

0 commit comments

Comments
 (0)