sound/soc/intel/boards/bytcht_es8316.c

Source file repositories/reference/linux-study-clean/sound/soc/intel/boards/bytcht_es8316.c

File Facts

System
Linux kernel
Corpus path
sound/soc/intel/boards/bytcht_es8316.c
Extension
.c
Size
21897 bytes
Lines
756
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 byt_cht_es8316_private {
	struct clk *mclk;
	struct snd_soc_jack jack;
	struct gpio_desc *speaker_en_gpio;
	struct device *codec_dev;
	bool speaker_en;
	bool mclk_enabled;
};

enum {
	BYT_CHT_ES8316_INTMIC_IN1_MAP,
	BYT_CHT_ES8316_INTMIC_IN2_MAP,
};

#define BYT_CHT_ES8316_MAP_MASK			GENMASK(3, 0)
#define BYT_CHT_ES8316_MAP(quirk)		((quirk) & BYT_CHT_ES8316_MAP_MASK)
#define BYT_CHT_ES8316_SSP0			BIT(16)
#define BYT_CHT_ES8316_MONO_SPEAKER		BIT(17)
#define BYT_CHT_ES8316_JD_INVERTED		BIT(18)

static unsigned long quirk;

static int quirk_override = -1;
module_param_named(quirk, quirk_override, int, 0444);
MODULE_PARM_DESC(quirk, "Board-specific quirk override");

static void log_quirks(struct device *dev)
{
	int map;

	map = BYT_CHT_ES8316_MAP(quirk);
	switch (map) {
	case BYT_CHT_ES8316_INTMIC_IN1_MAP:
		dev_info(dev, "quirk IN1_MAP enabled");
		break;
	case BYT_CHT_ES8316_INTMIC_IN2_MAP:
		dev_info(dev, "quirk IN2_MAP enabled");
		break;
	default:
		dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to INTMIC_IN1_MAP\n", map);
		quirk &= ~BYT_CHT_ES8316_MAP_MASK;
		quirk |= BYT_CHT_ES8316_INTMIC_IN1_MAP;
		break;
	}

	if (quirk & BYT_CHT_ES8316_SSP0)
		dev_info(dev, "quirk SSP0 enabled");
	if (quirk & BYT_CHT_ES8316_MONO_SPEAKER)
		dev_info(dev, "quirk MONO_SPEAKER enabled\n");
	if (quirk & BYT_CHT_ES8316_JD_INVERTED)
		dev_info(dev, "quirk JD_INVERTED enabled\n");
}

static int byt_cht_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
	struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);

	if (SND_SOC_DAPM_EVENT_ON(event))
		priv->speaker_en = true;
	else
		priv->speaker_en = false;

	gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);

	return 0;
}

static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = {
	SND_SOC_DAPM_SPK("Speaker", NULL),
	SND_SOC_DAPM_HP("Headphone", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
	SND_SOC_DAPM_MIC("Internal Mic", NULL),

	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
			    byt_cht_es8316_speaker_power_event,
			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
};

static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
	{"Headphone", NULL, "HPOL"},
	{"Headphone", NULL, "HPOR"},

	/*
	 * There is no separate speaker output instead the speakers are muxed to
	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
	 */
	{"Speaker", NULL, "HPOL"},
	{"Speaker", NULL, "HPOR"},

Annotation

Implementation Notes