sound/soc/codecs/audio-iio-aux.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/audio-iio-aux.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/audio-iio-aux.c
Extension
.c
Size
8726 bytes
Lines
315
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 audio_iio_aux_chan {
	struct iio_channel *iio_chan;
	const char *name;
	int max;
	int min;
	bool is_invert_range;
};

struct audio_iio_aux {
	struct device *dev;
	unsigned int num_chans;
	struct audio_iio_aux_chan chans[]  __counted_by(num_chans);
};

static int audio_iio_aux_info_volsw(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_info *uinfo)
{
	struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;

	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = chan->max - chan->min;
	uinfo->type = (uinfo->value.integer.max == 1) ?
			SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
	return 0;
}

static int audio_iio_aux_get_volsw(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;
	int max = chan->max;
	int min = chan->min;
	bool invert_range = chan->is_invert_range;
	int ret;
	int val;

	ret = iio_read_channel_raw(chan->iio_chan, &val);
	if (ret < 0)
		return ret;

	ucontrol->value.integer.value[0] = val - min;
	if (invert_range)
		ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0];

	return 0;
}

static int audio_iio_aux_put_volsw(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;
	int max = chan->max;
	int min = chan->min;
	bool invert_range = chan->is_invert_range;
	int val;
	int ret;
	int tmp;

	val = ucontrol->value.integer.value[0];
	if (val < 0)
		return -EINVAL;
	if (val > max - min)
		return -EINVAL;

	val = val + min;
	if (invert_range)
		val = max - val;

	ret = iio_read_channel_raw(chan->iio_chan, &tmp);
	if (ret < 0)
		return ret;

	if (tmp == val)
		return 0;

	ret = iio_write_channel_raw(chan->iio_chan, val);
	if (ret)
		return ret;

	return 1; /* The value changed */
}

static int audio_iio_aux_add_controls(struct snd_soc_component *component,
				      struct audio_iio_aux_chan *chan)
{
	struct snd_kcontrol_new control = {
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = chan->name,
		.info = audio_iio_aux_info_volsw,

Annotation

Implementation Notes