sound/soc/rockchip/rockchip_i2s_tdm.c

Source file repositories/reference/linux-study-clean/sound/soc/rockchip/rockchip_i2s_tdm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/rockchip/rockchip_i2s_tdm.c
Extension
.c
Size
37168 bytes
Lines
1442
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 txrx_config {
	u32 addr;
	u32 reg;
	u32 txonly;
	u32 rxonly;
};

struct rk_i2s_soc_data {
	u32 softrst_offset;
	u32 grf_reg_offset;
	u32 grf_shift;
	int config_count;
	const struct txrx_config *configs;
	int (*init)(struct device *dev, u32 addr);
};

struct rk_i2s_tdm_dev {
	struct device *dev;
	struct clk *hclk;
	struct clk *mclk_tx;
	struct clk *mclk_rx;
	struct regmap *regmap;
	struct regmap *grf;
	struct snd_dmaengine_dai_dma_data capture_dma_data;
	struct snd_dmaengine_dai_dma_data playback_dma_data;
	struct reset_control *tx_reset;
	struct reset_control *rx_reset;
	const struct rk_i2s_soc_data *soc_data;
	bool is_master_mode;
	bool io_multiplex;
	bool tdm_mode;
	unsigned int frame_width;
	unsigned int clk_trcm;
	unsigned int i2s_sdis[CH_GRP_MAX];
	unsigned int i2s_sdos[CH_GRP_MAX];
	int refcount;
	spinlock_t lock; /* xfer lock */
	bool has_playback;
	bool has_capture;
	struct snd_soc_dai_driver *dai;
	unsigned int mclk_rx_freq;
	unsigned int mclk_tx_freq;
};

static int to_ch_num(unsigned int val)
{
	switch (val) {
	case I2S_CHN_4:
		return 4;
	case I2S_CHN_6:
		return 6;
	case I2S_CHN_8:
		return 8;
	default:
		return 2;
	}
}

static void i2s_tdm_disable_unprepare_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
{
	clk_disable_unprepare(i2s_tdm->mclk_tx);
	clk_disable_unprepare(i2s_tdm->mclk_rx);
}

/**
 * i2s_tdm_prepare_enable_mclk - prepare to enable all mclks, disable them on
 *				 failure.
 * @i2s_tdm: rk_i2s_tdm_dev struct
 *
 * This function attempts to enable all mclk clocks, but cleans up after
 * itself on failure. Guarantees to balance its calls.
 *
 * Returns success (0) or negative errno.
 */
static int i2s_tdm_prepare_enable_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
{
	int ret = 0;

	ret = clk_prepare_enable(i2s_tdm->mclk_tx);
	if (ret)
		goto err_mclk_tx;
	ret = clk_prepare_enable(i2s_tdm->mclk_rx);
	if (ret)
		goto err_mclk_rx;

	return 0;

err_mclk_rx:
	clk_disable_unprepare(i2s_tdm->mclk_tx);
err_mclk_tx:

Annotation

Implementation Notes