sound/soc/soc-ops.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/soc-ops.c
Extension
.c
Size
22494 bytes
Lines
819
Domain
Driver Families
Bucket
sound/soc
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

if (mc->reg == mc->rreg) {
			val1 |= soc_mixer_ctl_to_reg(mc,
						     ucontrol->value.integer.value[1],
						     mask, mc->rshift, max);
			val_mask |= mask << mc->rshift;
		} else {
			val2 = soc_mixer_ctl_to_reg(mc,
						    ucontrol->value.integer.value[1],
						    mask, mc->shift, max);
			double_r = true;
		}
	}

	ret = snd_soc_component_update_bits(component, mc->reg, val_mask, val1);
	if (ret < 0)
		return ret;

	if (double_r) {
		int err = snd_soc_component_update_bits(component, mc->rreg,
							val_mask, val2);
		/* Don't drop change flag */
		if (err)
			return err;
	}

	return ret;
}

static int soc_get_volsw(struct snd_kcontrol *kcontrol,
			 struct snd_ctl_elem_value *ucontrol,
			 struct soc_mixer_control *mc, int mask, int max, bool sx)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	unsigned int reg_val;
	int val;

	reg_val = snd_soc_component_read(component, mc->reg);
	val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);

	ucontrol->value.integer.value[0] = val;

	if (snd_soc_volsw_is_stereo(mc)) {
		if (mc->reg == mc->rreg) {
			val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max, sx);
		} else {
			reg_val = snd_soc_component_read(component, mc->rreg);
			val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
		}

		ucontrol->value.integer.value[1] = val;
	}

	return 0;
}

/**
 * snd_soc_info_volsw - single mixer info callback with range.
 * @kcontrol: mixer control
 * @uinfo: control element information
 *
 * Callback to provide information, with a range, about a single mixer control,
 * or a double mixer control that spans 2 registers.
 *
 * Returns 0 for success.
 */
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
		       struct snd_ctl_elem_info *uinfo)
{
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;

	return soc_info_volsw(kcontrol, uinfo, mc, mc->max - mc->min);
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw);

/**
 * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
 * @kcontrol: mixer control
 * @uinfo: control element information
 *
 * Callback to provide information about a single mixer control, or a double
 * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
 * have a range that represents both positive and negative values either side
 * of zero but without a sign bit. min is the minimum register value, max is
 * the number of steps.
 *
 * Returns 0 for success.
 */
int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
			  struct snd_ctl_elem_info *uinfo)

Annotation

Implementation Notes