Skip to content

Commit 61390d0

Browse files
committed
ASoC: SOF: Intel: add hda_dsp_dma_channel_pair_get/put helpers
Currently, hda_dsp_stream_get/put are used to get/put the host dma. However, we may want to use a hda stream that both host and link dma are available. Add helper to find the hda stream and reserve/release it. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent b250b54 commit 61390d0

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

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

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,3 +1211,112 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
12111211
return ((u64)ldp_u << 32) | ldp_l;
12121212
}
12131213
EXPORT_SYMBOL_NS(hda_dsp_get_stream_ldp, "SND_SOC_SOF_INTEL_HDA_COMMON");
1214+
1215+
struct hdac_ext_stream*
1216+
hda_dsp_dma_channel_pair_get(struct device *dev, unsigned int format, unsigned int size,
1217+
struct snd_dma_buffer *dmab, int direction)
1218+
{
1219+
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
1220+
struct hdac_ext_stream *hext_stream = NULL;
1221+
struct hdac_bus *bus = sof_to_bus(sdev);
1222+
struct sof_intel_hda_stream *hda_stream;
1223+
struct hdac_stream *hstream;
1224+
bool found = false;
1225+
int ret;
1226+
1227+
spin_lock_irq(&bus->reg_lock);
1228+
1229+
/* get an unused stream */
1230+
list_for_each_entry(hstream, &bus->stream_list, list) {
1231+
if (hstream->direction == direction && !hstream->opened) {
1232+
hext_stream = stream_to_hdac_ext_stream(hstream);
1233+
hda_stream = container_of(hext_stream,
1234+
struct sof_intel_hda_stream,
1235+
hext_stream);
1236+
/* check if the host and link DMA channel is reserved */
1237+
if (hda_stream->host_reserved || hext_stream->link_locked)
1238+
continue;
1239+
1240+
hstream->opened = true;
1241+
hext_stream->link_locked = true;
1242+
found = true;
1243+
break;
1244+
}
1245+
}
1246+
1247+
spin_unlock_irq(&bus->reg_lock);
1248+
1249+
if (!found) {
1250+
dev_err(sdev->dev, "%s: no stream available\n", __func__);
1251+
return ERR_PTR(-ENODEV);
1252+
}
1253+
hstream->substream = NULL;
1254+
1255+
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
1256+
if (ret < 0) {
1257+
dev_err(sdev->dev, "%s: memory alloc failed: %d\n",
1258+
__func__, ret);
1259+
goto out_put;
1260+
}
1261+
1262+
hstream->period_bytes = 0; /* initialize period_bytes */
1263+
hstream->format_val = format;
1264+
hstream->bufsize = size;
1265+
1266+
ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
1267+
if (ret < 0) {
1268+
dev_err(sdev->dev, "%s: hdac prepare failed: %d\n", __func__, ret);
1269+
goto out_free;
1270+
}
1271+
hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_ENABLE, size);
1272+
1273+
return hext_stream;
1274+
1275+
out_free:
1276+
snd_dma_free_pages(dmab);
1277+
dmab->area = NULL;
1278+
dmab->bytes = 0;
1279+
hstream->bufsize = 0;
1280+
hstream->format_val = 0;
1281+
out_put:
1282+
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
1283+
return ERR_PTR(ret);
1284+
}
1285+
EXPORT_SYMBOL_NS(hda_dsp_dma_channel_pair_get, "SND_SOC_SOF_INTEL_HDA_COMMON");
1286+
1287+
int hda_dsp_dma_channel_pair_put(struct device *dev, struct snd_dma_buffer *dmab,
1288+
struct hdac_ext_stream *hext_stream)
1289+
{
1290+
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
1291+
struct hdac_stream *hstream = hdac_stream(hext_stream);
1292+
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
1293+
int ret = 0;
1294+
1295+
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
1296+
ret = hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0);
1297+
else
1298+
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
1299+
SOF_HDA_SD_CTL_DMA_START, 0);
1300+
1301+
hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
1302+
snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
1303+
1304+
hstream->substream = NULL;
1305+
1306+
/* reset BDL address */
1307+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
1308+
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL, 0);
1309+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
1310+
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);
1311+
1312+
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0);
1313+
1314+
snd_dma_free_pages(dmab);
1315+
dmab->area = NULL;
1316+
dmab->bytes = 0;
1317+
hstream->bufsize = 0;
1318+
hstream->format_val = 0;
1319+
1320+
return ret;
1321+
}
1322+
EXPORT_SYMBOL_NS(hda_dsp_dma_channel_pair_put, "SND_SOC_SOF_INTEL_HDA_COMMON");

sound/soc/sof/intel/hda.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,12 @@ int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
902902
int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd,
903903
struct snd_soc_dai *cpu_dai);
904904

905+
struct hdac_ext_stream*
906+
hda_dsp_dma_channel_pair_get(struct device *dev, unsigned int format, unsigned int size,
907+
struct snd_dma_buffer *dmab, int direction);
908+
909+
int hda_dsp_dma_channel_pair_put(struct device *dev, struct snd_dma_buffer *dmab,
910+
struct hdac_ext_stream *hext_stream);
905911
/* common dai driver */
906912
extern struct snd_soc_dai_driver skl_dai[];
907913
int hda_dsp_dais_suspend(struct snd_sof_dev *sdev);

0 commit comments

Comments
 (0)