sound/soc/codecs/ntp8918.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/ntp8918.c
Extension
.c
Size
10167 bytes
Lines
397
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 ntp8918_priv {
	struct i2c_client *i2c;
	struct clk *bck;
	struct reset_control *reset;
	unsigned int format;
};

static const DECLARE_TLV_DB_SCALE(ntp8918_master_vol_scale, -12550, 50, 0);

static const struct snd_kcontrol_new ntp8918_vol_control[] = {
	SOC_SINGLE_RANGE_TLV("Playback Volume", NTP8918_MASTER_VOL, 0,
			     0x04, 0xff, 0, ntp8918_master_vol_scale),
	SOC_SINGLE("Playback Switch", NTP8918_PWM_MASK_CTRL0, 1, 1, 1),
};

static void ntp8918_reset_gpio(struct ntp8918_priv *ntp8918)
{
	/*
	 * Proper initialization sequence for NTP8918 amplifier requires driving
	 * /RESET signal low during power up for at least 0.1us. The sequence is,
	 * according to NTP8918 datasheet, 6.2 Timing Sequence 1:
	 * Deassert for T2 >= 1ms...
	 */
	reset_control_deassert(ntp8918->reset);
	fsleep(1000);

	/* ...Assert for T3 >= 0.1us... */
	reset_control_assert(ntp8918->reset);
	fsleep(1);

	/* ...Deassert, and wait for T4 >= 0.5ms before sound on sequence. */
	reset_control_deassert(ntp8918->reset);
	fsleep(500);
}

static const struct reg_sequence ntp8918_sound_off[] = {
	{ NTP8918_MASTER_VOL, 0 },
};

static const struct reg_sequence ntp8918_sound_on[] = {
	{ NTP8918_MASTER_VOL, 0b11 },
};

static int ntp8918_load_firmware(struct ntp8918_priv *ntp8918)
{
	int ret;

	ret = ntpfw_load(ntp8918->i2c, NTP8918_FW_NAME, NTP8918_FW_MAGIC);
	if (ret == -ENOENT) {
		dev_warn_once(&ntp8918->i2c->dev, "Could not find firmware %s\n",
			      NTP8918_FW_NAME);
		return 0;
	}

	return ret;
}

static int ntp8918_snd_suspend(struct snd_soc_component *component)
{
	struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);

	regcache_cache_only(component->regmap, true);

	regmap_multi_reg_write_bypassed(component->regmap,
					ntp8918_sound_off,
					ARRAY_SIZE(ntp8918_sound_off));

	/*
	 * According to NTP8918 datasheet, 6.2 Timing Sequence 1:
	 * wait after sound off for T6 >= 0.5ms
	 */
	fsleep(500);
	reset_control_assert(ntp8918->reset);

	regcache_mark_dirty(component->regmap);
	clk_disable_unprepare(ntp8918->bck);

	return 0;
}

static int ntp8918_snd_resume(struct snd_soc_component *component)
{
	struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
	int ret;

	ret = clk_prepare_enable(ntp8918->bck);
	if (ret)
		return ret;

	ntp8918_reset_gpio(ntp8918);

Annotation

Implementation Notes