sound/soc/pxa/pxa-ssp.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/pxa/pxa-ssp.c
Extension
.c
Size
21414 bytes
Lines
888
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 ssp_priv {
	struct ssp_device *ssp;
	struct clk *extclk;
	unsigned long ssp_clk;
	unsigned int sysclk;
	unsigned int dai_fmt;
	unsigned int configured_dai_fmt;
#ifdef CONFIG_PM
	uint32_t	cr0;
	uint32_t	cr1;
	uint32_t	to;
	uint32_t	psp;
#endif
};

static void dump_registers(struct ssp_device *ssp)
{
	dev_dbg(ssp->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
		 pxa_ssp_read_reg(ssp, SSCR0), pxa_ssp_read_reg(ssp, SSCR1),
		 pxa_ssp_read_reg(ssp, SSTO));

	dev_dbg(ssp->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
		 pxa_ssp_read_reg(ssp, SSPSP), pxa_ssp_read_reg(ssp, SSSR),
		 pxa_ssp_read_reg(ssp, SSACD));
}

static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4,
			int out, struct snd_dmaengine_dai_dma_data *dma)
{
	dma->addr_width = width4 ? DMA_SLAVE_BUSWIDTH_4_BYTES :
				   DMA_SLAVE_BUSWIDTH_2_BYTES;
	dma->maxburst = 16;
	dma->addr = ssp->phys_base + SSDR;
}

static int pxa_ssp_startup(struct snd_pcm_substream *substream,
			   struct snd_soc_dai *cpu_dai)
{
	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
	struct ssp_device *ssp = priv->ssp;
	struct snd_dmaengine_dai_dma_data *dma;
	int ret = 0;

	if (!snd_soc_dai_active(cpu_dai)) {
		clk_prepare_enable(ssp->clk);
		pxa_ssp_disable(ssp);
	}

	clk_prepare_enable(priv->extclk);

	dma = kzalloc_obj(struct snd_dmaengine_dai_dma_data);
	if (!dma)
		return -ENOMEM;
	dma->chan_name = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
		"tx" : "rx";

	snd_soc_dai_set_dma_data(cpu_dai, substream, dma);

	return ret;
}

static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
			     struct snd_soc_dai *cpu_dai)
{
	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
	struct ssp_device *ssp = priv->ssp;

	if (!snd_soc_dai_active(cpu_dai)) {
		pxa_ssp_disable(ssp);
		clk_disable_unprepare(ssp->clk);
	}

	clk_disable_unprepare(priv->extclk);

	kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
	snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
}

#ifdef CONFIG_PM

static int pxa_ssp_suspend(struct snd_soc_component *component)
{
	struct ssp_priv *priv = snd_soc_component_get_drvdata(component);
	struct ssp_device *ssp = priv->ssp;

	if (!snd_soc_component_active(component))
		clk_prepare_enable(ssp->clk);

	priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0);
	priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1);

Annotation

Implementation Notes