sound/i2c/other/ak4xxx-adda.c

Source file repositories/reference/linux-study-clean/sound/i2c/other/ak4xxx-adda.c

File Facts

System
Linux kernel
Corpus path
sound/i2c/other/ak4xxx-adda.c
Extension
.c
Size
26338 bytes
Lines
923
Domain
Driver Families
Bucket
sound/i2c
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

while (*ptr != 0xff) {
			reg = *ptr++;
			data = *ptr++;
			snd_akm4xxx_write(ak, chip, reg, data);
			udelay(10);
		}
	}
}

EXPORT_SYMBOL(snd_akm4xxx_init);

/*
 * Mixer callbacks
 */
#define AK_IPGA 			(1<<20)	/* including IPGA */
#define AK_VOL_CVT 			(1<<21)	/* need dB conversion */
#define AK_NEEDSMSB 			(1<<22)	/* need MSB update bit */
#define AK_INVERT 			(1<<23)	/* data is inverted */
#define AK_GET_CHIP(val)		(((val) >> 8) & 0xff)
#define AK_GET_ADDR(val)		((val) & 0xff)
#define AK_GET_SHIFT(val)		(((val) >> 16) & 0x0f)
#define AK_GET_VOL_CVT(val)		(((val) >> 21) & 1)
#define AK_GET_IPGA(val)		(((val) >> 20) & 1)
#define AK_GET_NEEDSMSB(val)		(((val) >> 22) & 1)
#define AK_GET_INVERT(val)		(((val) >> 23) & 1)
#define AK_GET_MASK(val)		(((val) >> 24) & 0xff)
#define AK_COMPOSE(chip,addr,shift,mask) \
	(((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))

static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_info *uinfo)
{
	unsigned int mask = AK_GET_MASK(kcontrol->private_value);

	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = mask;
	return 0;
}

static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
	int chip = AK_GET_CHIP(kcontrol->private_value);
	int addr = AK_GET_ADDR(kcontrol->private_value);

	ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr);
	return 0;
}

static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
		      unsigned char nval)
{
	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
	unsigned int mask = AK_GET_MASK(kcontrol->private_value);
	int chip = AK_GET_CHIP(kcontrol->private_value);

	if (snd_akm4xxx_get_vol(ak, chip, addr) == nval)
		return 0;

	snd_akm4xxx_set_vol(ak, chip, addr, nval);
	if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128)
		nval = vol_cvt_datt[nval];
	if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128)
		nval++; /* need to correct + 1 since both 127 and 128 are 0dB */
	if (AK_GET_INVERT(kcontrol->private_value))
		nval = mask - nval;
	if (AK_GET_NEEDSMSB(kcontrol->private_value))
		nval |= 0x80;
	snd_akm4xxx_write(ak, chip, addr, nval);
	return 1;
}

static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	unsigned int mask = AK_GET_MASK(kcontrol->private_value);
	unsigned int val = ucontrol->value.integer.value[0];
	if (val > mask)
		return -EINVAL;
	return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val);
}

static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_info *uinfo)
{
	unsigned int mask = AK_GET_MASK(kcontrol->private_value);

Annotation

Implementation Notes