sound/soc/pxa/mmp-sspa.c

Source file repositories/reference/linux-study-clean/sound/soc/pxa/mmp-sspa.c

File Facts

System
Linux kernel
Corpus path
sound/soc/pxa/mmp-sspa.c
Extension
.c
Size
13770 bytes
Lines
586
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source 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

struct sspa_priv {
	void __iomem *tx_base;
	void __iomem *rx_base;

	struct snd_dmaengine_dai_dma_data playback_dma_data;
	struct snd_dmaengine_dai_dma_data capture_dma_data;
	struct clk *clk;
	struct clk *audio_clk;
	struct clk *sysclk;

	int running_cnt;
	u32 sp;
	u32 ctrl;
};

static void mmp_sspa_tx_enable(struct sspa_priv *sspa)
{
	unsigned int sspa_sp = sspa->sp;

	sspa_sp &= ~SSPA_SP_MSL;
	sspa_sp |= SSPA_SP_S_EN;
	sspa_sp |= SSPA_SP_WEN;
	__raw_writel(sspa_sp, sspa->tx_base + SSPA_SP);
}

static void mmp_sspa_tx_disable(struct sspa_priv *sspa)
{
	unsigned int sspa_sp = sspa->sp;

	sspa_sp &= ~SSPA_SP_MSL;
	sspa_sp &= ~SSPA_SP_S_EN;
	sspa_sp |= SSPA_SP_WEN;
	__raw_writel(sspa_sp, sspa->tx_base + SSPA_SP);
}

static void mmp_sspa_rx_enable(struct sspa_priv *sspa)
{
	unsigned int sspa_sp = sspa->sp;

	sspa_sp |= SSPA_SP_S_EN;
	sspa_sp |= SSPA_SP_WEN;
	__raw_writel(sspa_sp, sspa->rx_base + SSPA_SP);
}

static void mmp_sspa_rx_disable(struct sspa_priv *sspa)
{
	unsigned int sspa_sp = sspa->sp;

	sspa_sp &= ~SSPA_SP_S_EN;
	sspa_sp |= SSPA_SP_WEN;
	__raw_writel(sspa_sp, sspa->rx_base + SSPA_SP);
}

static int mmp_sspa_startup(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);

	clk_prepare_enable(sspa->sysclk);
	clk_prepare_enable(sspa->clk);

	return 0;
}

static void mmp_sspa_shutdown(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);

	clk_disable_unprepare(sspa->clk);
	clk_disable_unprepare(sspa->sysclk);
}

/*
 * Set the SSP ports SYSCLK.
 */
static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
				    int clk_id, unsigned int freq, int dir)
{
	struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai);
	struct device *dev = cpu_dai->component->dev;
	int ret = 0;

	if (dev->of_node)
		return -ENOTSUPP;

	switch (clk_id) {
	case MMP_SSPA_CLK_AUDIO:
		ret = clk_set_rate(sspa->audio_clk, freq);
		if (ret)

Annotation

Implementation Notes