sound/soc/starfive/jh7110_tdm.c

Source file repositories/reference/linux-study-clean/sound/soc/starfive/jh7110_tdm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/starfive/jh7110_tdm.c
Extension
.c
Size
15876 bytes
Lines
663
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 tdm_chan_cfg {
	enum TDM_IFL ifl;
	enum TDM_WL  wl;
	unsigned char sscale;
	enum TDM_SL  sl;
	enum TDM_LRJ lrj;
	unsigned char enable;
};

struct jh7110_tdm_dev {
	void __iomem *tdm_base;
	struct device *dev;
	struct clk_bulk_data clks[6];
	struct reset_control *resets;

	enum TDM_CLKPOL clkpolity;
	enum TDM_ELM	elm;
	enum TDM_SYNCM	syncm;
	enum TDM_MASTER_SLAVE_MODE ms_mode;

	struct tdm_chan_cfg tx;
	struct tdm_chan_cfg rx;

	u16 syncdiv;
	u32 samplerate;
	u32 pcmclk;

	/* data related to DMA transfers b/w tdm and DMAC */
	struct snd_dmaengine_dai_dma_data play_dma_data;
	struct snd_dmaengine_dai_dma_data capture_dma_data;
	u32 saved_pcmgbcr;
	u32 saved_pcmtxcr;
	u32 saved_pcmrxcr;
	u32 saved_pcmdiv;
};

static inline u32 jh7110_tdm_readl(struct jh7110_tdm_dev *tdm, u16 reg)
{
	return readl_relaxed(tdm->tdm_base + reg);
}

static inline void jh7110_tdm_writel(struct jh7110_tdm_dev *tdm, u16 reg, u32 val)
{
	writel_relaxed(val, tdm->tdm_base + reg);
}

static void jh7110_tdm_save_context(struct jh7110_tdm_dev *tdm,
				    struct snd_pcm_substream *substream)
{
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		tdm->saved_pcmtxcr = jh7110_tdm_readl(tdm, TDM_PCMTXCR);
	else
		tdm->saved_pcmrxcr = jh7110_tdm_readl(tdm, TDM_PCMRXCR);
}

static void jh7110_tdm_start(struct jh7110_tdm_dev *tdm,
			     struct snd_pcm_substream *substream)
{
	u32 data;

	data = jh7110_tdm_readl(tdm, TDM_PCMGBCR);
	jh7110_tdm_writel(tdm, TDM_PCMGBCR, data | PCMGBCR_ENABLE);

	/* restore context */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		jh7110_tdm_writel(tdm, TDM_PCMTXCR, tdm->saved_pcmtxcr | PCMTXCR_TXEN);
	else
		jh7110_tdm_writel(tdm, TDM_PCMRXCR, tdm->saved_pcmrxcr | PCMRXCR_RXEN);
}

static void jh7110_tdm_stop(struct jh7110_tdm_dev *tdm,
			    struct snd_pcm_substream *substream)
{
	unsigned int val;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		val = jh7110_tdm_readl(tdm, TDM_PCMTXCR);
		val &= ~PCMTXCR_TXEN;
		jh7110_tdm_writel(tdm, TDM_PCMTXCR, val);
	} else {
		val = jh7110_tdm_readl(tdm, TDM_PCMRXCR);
		val &= ~PCMRXCR_RXEN;
		jh7110_tdm_writel(tdm, TDM_PCMRXCR, val);
	}
}

static int jh7110_tdm_syncdiv(struct jh7110_tdm_dev *tdm)
{
	u32 sl, sscale, syncdiv;

Annotation

Implementation Notes