sound/aoa/codecs/tas.c

Source file repositories/reference/linux-study-clean/sound/aoa/codecs/tas.c

File Facts

System
Linux kernel
Corpus path
sound/aoa/codecs/tas.c
Extension
.c
Size
23616 bytes
Lines
911
Domain
Driver Families
Bucket
sound/aoa
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 tas {
	struct aoa_codec	codec;
	struct i2c_client	*i2c;
	u32			mute_l:1, mute_r:1 ,
				controls_created:1 ,
				drc_enabled:1,
				hw_enabled:1;
	u8			cached_volume_l, cached_volume_r;
	u8			mixer_l[3], mixer_r[3];
	u8			bass, treble;
	u8			acr;
	int			drc_range;
	/* protects hardware access against concurrency from
	 * userspace when hitting controls and during
	 * codec init/suspend/resume */
	struct mutex		mtx;
};

static int tas_reset_init(struct tas *tas);

static struct tas *codec_to_tas(struct aoa_codec *codec)
{
	return container_of(codec, struct tas, codec);
}

static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
{
	if (len == 1)
		return i2c_smbus_write_byte_data(tas->i2c, reg, *data);
	else
		return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data);
}

static void tas3004_set_drc(struct tas *tas)
{
	unsigned char val[6];

	if (tas->drc_enabled)
		val[0] = 0x50; /* 3:1 above threshold */
	else
		val[0] = 0x51; /* disabled */
	val[1] = 0x02; /* 1:1 below threshold */
	if (tas->drc_range > 0xef)
		val[2] = 0xef;
	else if (tas->drc_range < 0)
		val[2] = 0x00;
	else
		val[2] = tas->drc_range;
	val[3] = 0xb0;
	val[4] = 0x60;
	val[5] = 0xa0;

	tas_write_reg(tas, TAS_REG_DRC, 6, val);
}

static void tas_set_treble(struct tas *tas)
{
	u8 tmp;

	tmp = tas3004_treble(tas->treble);
	tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
}

static void tas_set_bass(struct tas *tas)
{
	u8 tmp;

	tmp = tas3004_bass(tas->bass);
	tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
}

static void tas_set_volume(struct tas *tas)
{
	u8 block[6];
	int tmp;
	u8 left, right;

	left = tas->cached_volume_l;
	right = tas->cached_volume_r;

	if (left > 177) left = 177;
	if (right > 177) right = 177;

	if (tas->mute_l) left = 0;
	if (tas->mute_r) right = 0;

	/* analysing the volume and mixer tables shows
	 * that they are similar enough when we shift
	 * the mixer table down by 4 bits. The error
	 * is miniscule, in just one item the error

Annotation

Implementation Notes