sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c

Source file repositories/reference/linux-study-clean/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c

File Facts

System
Linux kernel
Corpus path
sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c
Extension
.c
Size
13525 bytes
Lines
456
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 acp3x_es83xx_private {
	bool speaker_on;
	bool headphone_on;
	unsigned long quirk;
	struct snd_soc_component *codec;
	struct device *codec_dev;
	struct gpio_desc *gpio_speakers, *gpio_headphone;
	struct acpi_gpio_params enable_spk_gpio, enable_hp_gpio;
	struct acpi_gpio_mapping gpio_mapping[3];
	struct snd_soc_dapm_route mic_map[2];
};

static const unsigned int channels[] = {
	DUAL_CHANNEL,
};

static const struct snd_pcm_hw_constraint_list constraints_channels = {
	.count = ARRAY_SIZE(channels),
	.list = channels,
	.mask = 0,
};

#define ES83xx_12288_KHZ_MCLK_FREQ   (48000 * 256)
#define ES83xx_48_MHZ_MCLK_FREQ      (48000 * 1000)

static int acp3x_es83xx_headphone_power_event(struct snd_soc_dapm_widget *w,
					    struct snd_kcontrol *kcontrol, int event);
static int acp3x_es83xx_speaker_power_event(struct snd_soc_dapm_widget *w,
					    struct snd_kcontrol *kcontrol, int event);

static int acp3x_es83xx_codec_startup(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime;
	struct snd_soc_pcm_runtime *rtd;
	struct snd_soc_dai *codec_dai;
	struct acp3x_es83xx_private *priv;
	unsigned int freq;
	int ret;

	runtime = substream->runtime;
	rtd = snd_soc_substream_to_rtd(substream);
	codec_dai = snd_soc_rtd_to_codec(rtd, 0);
	priv = get_mach_priv(rtd->card);

	if (priv->quirk & ES83XX_48_MHZ_MCLK) {
		dev_dbg(priv->codec_dev, "using a 48Mhz MCLK\n");
		freq = ES83xx_48_MHZ_MCLK_FREQ;
	} else {
		dev_dbg(priv->codec_dev, "using a 12.288Mhz MCLK\n");
		freq = ES83xx_12288_KHZ_MCLK_FREQ;
	}

	ret = snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_OUT);
	if (ret < 0) {
		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
		return ret;
	}

	runtime->hw.channels_max = DUAL_CHANNEL;
	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
				   &constraints_channels);

	return 0;
}

static struct snd_soc_jack es83xx_jack;

static struct snd_soc_jack_pin es83xx_jack_pins[] = {
	{
		.pin	= "Headphone",
		.mask	= SND_JACK_HEADPHONE,
	},
	{
		.pin	= "Headset Mic",
		.mask	= SND_JACK_MICROPHONE,
	},
};

static const struct snd_soc_dapm_widget acp3x_es83xx_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("Headphone Power", SND_SOC_NOPM, 0, 0,
			    acp3x_es83xx_headphone_power_event,
			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
			    acp3x_es83xx_speaker_power_event,
			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),

Annotation

Implementation Notes