sound/soc/sof/intel/hda-sdw-bpt.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/intel/hda-sdw-bpt.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/intel/hda-sdw-bpt.c
Extension
.c
Size
14016 bytes
Lines
471
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret < 0) {
			dev_err(sdev->dev, "%s: chain_dma_trigger failed: %d\n",
				__func__, ret);
			hda_cl_trigger(sdev->dev, sdw_bpt_stream, SNDRV_PCM_TRIGGER_STOP);
			return ret;
		}
		snd_hdac_ext_stream_start(sdw_bpt_stream);
	}

	return ret;
}

static int hda_sdw_bpt_dma_disable(struct device *dev, struct hdac_ext_stream *sdw_bpt_stream)
{
	struct snd_sof_dev *sdev = dev_get_drvdata(dev);
	int ret;

	if (!sdev->dspless_mode_selected) {
		snd_hdac_ext_stream_clear(sdw_bpt_stream);

		ret = chain_dma_trigger(sdev, hdac_stream(sdw_bpt_stream)->stream_tag,
					hdac_stream(sdw_bpt_stream)->direction,
					SOF_IPC4_PIPE_PAUSED);
		if (ret < 0)
			dev_err(sdev->dev, "%s: chain_dma_trigger PIPE_PAUSED failed: %d\n",
				__func__, ret);
	}

	ret = hda_cl_trigger(sdev->dev, sdw_bpt_stream, SNDRV_PCM_TRIGGER_STOP);
	if (ret < 0)
		dev_err(sdev->dev, "%s: SDW BPT DMA trigger stop failed\n", __func__);

	return ret;
}

#define FIFO_ALIGNMENT	64

unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth)
{
	unsigned int num_channels = DIV_ROUND_UP(dma_bandwidth, BPT_FREQUENCY * 32);
	unsigned int data_block = num_channels * 4;
	unsigned int alignment = lcm(data_block, FIFO_ALIGNMENT);

	return alignment;
}
EXPORT_SYMBOL_NS(hda_sdw_bpt_get_buf_size_alignment, "SND_SOC_SOF_INTEL_HDA_SDW_BPT");

int hda_sdw_bpt_open(struct device *dev, int link_id, struct hdac_ext_stream **bpt_tx_stream,
		     struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes,
		     u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream,
		     struct snd_dma_buffer *dmab_rx_bdl, u32 bpt_rx_num_bytes,
		     u32 rx_dma_bandwidth)
{
	struct snd_sof_dev *sdev = dev_get_drvdata(dev);
	unsigned int num_channels_tx;
	unsigned int num_channels_rx;
	int ret1;
	int ret;

	num_channels_tx = DIV_ROUND_UP(tx_dma_bandwidth, BPT_FREQUENCY * 32);

	ret = hda_sdw_bpt_dma_prepare(dev, bpt_tx_stream, dmab_tx_bdl, bpt_tx_num_bytes,
				      num_channels_tx, SNDRV_PCM_STREAM_PLAYBACK);
	if (ret < 0) {
		dev_err(dev, "%s: hda_sdw_bpt_dma_prepare failed for TX: %d\n",
			__func__, ret);
		return ret;
	}

	num_channels_rx = DIV_ROUND_UP(rx_dma_bandwidth, BPT_FREQUENCY * 32);

	ret = hda_sdw_bpt_dma_prepare(dev, bpt_rx_stream, dmab_rx_bdl, bpt_rx_num_bytes,
				      num_channels_rx, SNDRV_PCM_STREAM_CAPTURE);
	if (ret < 0) {
		dev_err(dev, "%s: hda_sdw_bpt_dma_prepare failed for RX: %d\n",
			__func__, ret);

		ret1 = hda_sdw_bpt_dma_deprepare(dev, *bpt_tx_stream, dmab_tx_bdl);
		if (ret1 < 0)
			dev_err(dev, "%s: hda_sdw_bpt_dma_deprepare failed for TX: %d\n",
				__func__, ret1);
		return ret;
	}

	/* we need to map the channels in PCMSyCM registers */
	ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id,
					     0, /* cpu_dai->id -> PDI0 */
					     GENMASK(num_channels_tx - 1, 0),
					     hdac_stream(*bpt_tx_stream)->stream_tag,
					     SNDRV_PCM_STREAM_PLAYBACK);

Annotation

Implementation Notes