sound/soc/codecs/tas6424.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/tas6424.c
Extension
.c
Size
24157 bytes
Lines
817
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 tas6424_data {
	struct device *dev;
	struct regmap *regmap;
	struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES];
	struct delayed_work fault_check_work;
	unsigned int last_cfault;
	unsigned int last_fault1;
	unsigned int last_fault2;
	unsigned int last_warn;
	struct gpio_desc *standby_gpio;
	struct gpio_desc *mute_gpio;
};

/*
 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that
 * setting the gain below -100 dB (register value <0x7) is effectively a MUTE
 * as per device datasheet.
 */
static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0);

static const struct snd_kcontrol_new tas6424_snd_controls[] = {
	SOC_SINGLE_TLV("Speaker Driver CH1 Playback Volume",
		       TAS6424_CH1_VOL_CTRL, 0, 0xff, 0, dac_tlv),
	SOC_SINGLE_TLV("Speaker Driver CH2 Playback Volume",
		       TAS6424_CH2_VOL_CTRL, 0, 0xff, 0, dac_tlv),
	SOC_SINGLE_TLV("Speaker Driver CH3 Playback Volume",
		       TAS6424_CH3_VOL_CTRL, 0, 0xff, 0, dac_tlv),
	SOC_SINGLE_TLV("Speaker Driver CH4 Playback Volume",
		       TAS6424_CH4_VOL_CTRL, 0, 0xff, 0, dac_tlv),
	SOC_SINGLE_STROBE("Auto Diagnostics Switch", TAS6424_DC_DIAG_CTRL1,
			  TAS6424_LDGBYPASS_SHIFT, 1),
};

static int tas6424_dac_event(struct snd_soc_dapm_widget *w,
			     struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct tas6424_data *tas6424 = snd_soc_component_get_drvdata(component);

	dev_dbg(component->dev, "%s() event=0x%0x\n", __func__, event);

	if (event & SND_SOC_DAPM_POST_PMU) {
		/* Observe codec shutdown-to-active time */
		msleep(12);

		/* Turn on TAS6424 periodic fault checking/handling */
		tas6424->last_fault1 = 0;
		tas6424->last_fault2 = 0;
		tas6424->last_warn = 0;
		schedule_delayed_work(&tas6424->fault_check_work,
				      msecs_to_jiffies(TAS6424_FAULT_CHECK_INTERVAL));
	} else if (event & SND_SOC_DAPM_PRE_PMD) {
		/* Disable TAS6424 periodic fault checking/handling */
		cancel_delayed_work_sync(&tas6424->fault_check_work);
	}

	return 0;
}

static const struct snd_soc_dapm_widget tas6424_dapm_widgets[] = {
	SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas6424_dac_event,
			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
	SND_SOC_DAPM_OUTPUT("OUT")
};

static const struct snd_soc_dapm_route tas6424_audio_map[] = {
	{ "DAC", NULL, "DAC IN" },
	{ "OUT", NULL, "DAC" },
};

static int tas6424_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params,
			     struct snd_soc_dai *dai)
{
	struct snd_soc_component *component = dai->component;
	unsigned int rate = params_rate(params);
	unsigned int width = params_width(params);
	u8 sap_ctrl = 0;

	dev_dbg(component->dev, "%s() rate=%u width=%u\n", __func__, rate, width);

	switch (rate) {
	case 44100:
		sap_ctrl |= TAS6424_SAP_RATE_44100;
		break;
	case 48000:
		sap_ctrl |= TAS6424_SAP_RATE_48000;
		break;
	case 96000:

Annotation

Implementation Notes