sound/soc/hisilicon/hi6210-i2s.c

Source file repositories/reference/linux-study-clean/sound/soc/hisilicon/hi6210-i2s.c

File Facts

System
Linux kernel
Corpus path
sound/soc/hisilicon/hi6210-i2s.c
Extension
.c
Size
16433 bytes
Lines
610
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 hi6210_i2s {
	struct device *dev;
	struct reset_control *rc;
	struct clk *clk[8];
	int clocks;
	struct snd_soc_dai_driver dai;
	void __iomem *base;
	struct regmap *sysctrl;
	phys_addr_t base_phys;
	struct snd_dmaengine_dai_dma_data dma_data[2];
	int clk_rate;
	spinlock_t lock;
	int rate;
	int format;
	u8 bits;
	u8 channels;
	u8 id;
	u8 channel_length;
	u8 use;
	u32 master:1;
	u32 status:1;
};

#define SC_PERIPH_CLKEN1	0x210
#define SC_PERIPH_CLKDIS1	0x214

#define SC_PERIPH_CLKEN3	0x230
#define SC_PERIPH_CLKDIS3	0x234

#define SC_PERIPH_CLKEN12	0x270
#define SC_PERIPH_CLKDIS12	0x274

#define SC_PERIPH_RSTEN1	0x310
#define SC_PERIPH_RSTDIS1	0x314
#define SC_PERIPH_RSTSTAT1	0x318

#define SC_PERIPH_RSTEN2	0x320
#define SC_PERIPH_RSTDIS2	0x324
#define SC_PERIPH_RSTSTAT2	0x328

#define SOC_PMCTRL_BBPPLLALIAS	0x48

enum {
	CLK_DACODEC,
	CLK_I2S_BASE,
};

static inline void hi6210_write_reg(struct hi6210_i2s *i2s, int reg, u32 val)
{
	writel(val, i2s->base + reg);
}

static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg)
{
	return readl(i2s->base + reg);
}

static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
			      struct snd_soc_dai *cpu_dai)
{
	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
	int ret, n;
	u32 val;

	/* deassert reset on ABB */
	regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val);
	if (val & BIT(4))
		regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4));

	for (n = 0; n < i2s->clocks; n++) {
		ret = clk_prepare_enable(i2s->clk[n]);
		if (ret)
			goto err_unprepare_clk;
	}

	ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000);
	if (ret) {
		dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",
			__func__, ret);
		goto err_unprepare_clk;
	}

	/* enable clock before frequency division */
	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9));

	/* enable codec working clock / == "codec bus clock" */
	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5));

	/* deassert reset on codec / interface clock / working clock */
	regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));

Annotation

Implementation Notes