sound/hda/codecs/cirrus/cs8409.c

Source file repositories/reference/linux-study-clean/sound/hda/codecs/cirrus/cs8409.c

File Facts

System
Linux kernel
Corpus path
sound/hda/codecs/cirrus/cs8409.c
Extension
.c
Size
48071 bytes
Lines
1638
Domain
Driver Families
Bucket
sound/hda
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

if (vol_type == CS42L42_VOL_DAC) {
			if (chs & BIT(0))
				cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL, 0x3f);
			if (chs & BIT(1))
				cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL, 0x3f);
		} else if (vol_type == CS42L42_VOL_ADC) {
			if (chs & BIT(0))
				cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME, 0x9f);
		}
	} else {
		if (vol_type == CS42L42_VOL_DAC) {
			if (chs & BIT(0))
				cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL,
					-(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
					& CS42L42_MIXER_CH_VOL_MASK);
			if (chs & BIT(1))
				cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL,
					-(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
					& CS42L42_MIXER_CH_VOL_MASK);
		} else if (vol_type == CS42L42_VOL_ADC) {
			if (chs & BIT(0))
				cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME,
					cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
					& CS42L42_REG_AMIC_VOL_MASK);
		}
	}
}

int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
{
	struct hda_codec *codec = snd_kcontrol_chip(kctrl);
	struct cs8409_spec *spec = codec->spec;
	struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
	int chs = get_amp_channels(kctrl);
	unsigned int ofs = get_amp_offset(kctrl);
	long *valp = uctrl->value.integer.value;

	switch (ofs) {
	case CS42L42_VOL_DAC:
		if (chs & BIT(0))
			cs42l42->vol[ofs] = *valp;
		if (chs & BIT(1)) {
			valp++;
			cs42l42->vol[ofs + 1] = *valp;
		}
		if (spec->playback_started)
			cs42l42_mute(cs42l42, CS42L42_VOL_DAC, chs, false);
		break;
	case CS42L42_VOL_ADC:
		if (chs & BIT(0))
			cs42l42->vol[ofs] = *valp;
		if (spec->capture_started)
			cs42l42_mute(cs42l42, CS42L42_VOL_ADC, chs, false);
		break;
	default:
		break;
	}

	return 0;
}

static void cs42l42_playback_pcm_hook(struct hda_pcm_stream *hinfo,
				   struct hda_codec *codec,
				   struct snd_pcm_substream *substream,
				   int action)
{
	struct cs8409_spec *spec = codec->spec;
	struct sub_codec *cs42l42;
	int i;
	bool mute;

	switch (action) {
	case HDA_GEN_PCM_ACT_PREPARE:
		mute = false;
		spec->playback_started = 1;
		break;
	case HDA_GEN_PCM_ACT_CLEANUP:
		mute = true;
		spec->playback_started = 0;
		break;
	default:
		return;
	}

	for (i = 0; i < spec->num_scodecs; i++) {
		cs42l42 = spec->scodecs[i];
		cs42l42_mute(cs42l42, CS42L42_VOL_DAC, 0x3, mute);
	}
}

Annotation

Implementation Notes