sound/soc/rockchip/rockchip_i2s.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/rockchip/rockchip_i2s.c
Extension
.c
Size
20510 bytes
Lines
866
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 rk_i2s_pins {
	u32 reg_offset;
	u32 shift;
};

struct rk_i2s_dev {
	struct device *dev;

	struct clk *hclk;
	struct clk *mclk;

	struct snd_dmaengine_dai_dma_data capture_dma_data;
	struct snd_dmaengine_dai_dma_data playback_dma_data;

	struct regmap *regmap;
	struct regmap *grf;

	bool has_capture;
	bool has_playback;

/*
 * Used to indicate the tx/rx status.
 * I2S controller hopes to start the tx and rx together,
 * also to stop them when they are both try to stop.
*/
	bool tx_start;
	bool rx_start;
	bool is_master_mode;
	const struct rk_i2s_pins *pins;
	unsigned int bclk_ratio;
	spinlock_t lock; /* tx/rx lock */
	struct pinctrl *pinctrl;
	struct pinctrl_state *bclk_on;
	struct pinctrl_state *bclk_off;
};

static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
{
	int ret = 0;

	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_on);

	if (ret)
		dev_err(i2s->dev, "bclk enable failed %d\n", ret);

	return ret;
}

static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
{

	int ret = 0;

	if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
		ret = pinctrl_select_state(i2s->pinctrl, i2s->bclk_off);

	if (ret)
		dev_err(i2s->dev, "bclk disable failed %d\n", ret);

	return ret;
}

static int i2s_runtime_suspend(struct device *dev)
{
	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);

	regcache_cache_only(i2s->regmap, true);
	clk_disable_unprepare(i2s->mclk);

	return 0;
}

static int i2s_runtime_resume(struct device *dev)
{
	struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
	int ret;

	ret = clk_prepare_enable(i2s->mclk);
	if (ret) {
		dev_err(i2s->dev, "clock enable failed %d\n", ret);
		return ret;
	}

	regcache_cache_only(i2s->regmap, false);
	regcache_mark_dirty(i2s->regmap);

	ret = regcache_sync(i2s->regmap);
	if (ret)
		clk_disable_unprepare(i2s->mclk);

Annotation

Implementation Notes