@@ -1211,3 +1211,112 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
12111211 return ((u64 )ldp_u << 32 ) | ldp_l ;
12121212}
12131213EXPORT_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" );
0 commit comments