sound/soc/codecs/wm2000.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/wm2000.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/wm2000.c
Extension
.c
Size
23189 bytes
Lines
950
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 wm2000_priv {
	struct i2c_client *i2c;
	struct regmap *regmap;
	struct clk *mclk;

	struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES];

	enum wm2000_anc_mode anc_mode;

	unsigned int anc_active:1;
	unsigned int anc_eng_ena:1;
	unsigned int spk_ena:1;

	unsigned int speech_clarity:1;

	int anc_download_size;
	char *anc_download;

	struct mutex lock;
};

static int wm2000_write(struct i2c_client *i2c, unsigned int reg,
			unsigned int value)
{
	struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
	return regmap_write(wm2000->regmap, reg, value);
}

static void wm2000_reset(struct wm2000_priv *wm2000)
{
	struct i2c_client *i2c = wm2000->i2c;

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);
	wm2000_write(i2c, WM2000_REG_ID1, 0);

	wm2000->anc_mode = ANC_OFF;
}

static int wm2000_poll_bit(struct i2c_client *i2c,
			   unsigned int reg, u8 mask)
{
	struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
	int timeout = 4000;
	unsigned int val;

	regmap_read(wm2000->regmap, reg, &val);

	while (!(val & mask) && --timeout) {
		msleep(1);
		regmap_read(wm2000->regmap, reg, &val);
	}

	if (timeout == 0)
		return 0;
	else
		return 1;
}

static int wm2000_power_up(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	unsigned long rate;
	unsigned int val;
	int ret;

	if (WARN_ON(wm2000->anc_mode != ANC_OFF))
		return -EINVAL;

	dev_dbg(&i2c->dev, "Beginning power up\n");

	ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
		return ret;
	}

	rate = clk_get_rate(wm2000->mclk);
	if (rate <= 13500000) {
		dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_CLR);
	} else {
		dev_dbg(&i2c->dev, "Enabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_SET);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET);

Annotation

Implementation Notes