sound/soc/intel/boards/ehl_rt5660.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/intel/boards/ehl_rt5660.c
Extension
.c
Size
7850 bytes
Lines
315
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 sof_card_private {
	struct list_head hdmi_pcm_list;
	bool idisp_codec;
};

static const struct snd_kcontrol_new rt5660_controls[] = {
	SOC_DAPM_PIN_SWITCH("Speaker"),
	/* There are two MICBIAS in rt5660, each for one MIC */
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
	SOC_DAPM_PIN_SWITCH("Headset Mic2"),
	SOC_DAPM_PIN_SWITCH("Line Out"),
};

static const struct snd_soc_dapm_widget rt5660_widgets[] = {
	SND_SOC_DAPM_SPK("Speaker", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
	SND_SOC_DAPM_MIC("Headset Mic2", NULL),
	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
	SND_SOC_DAPM_LINE("Line Out", NULL),
};

static const struct snd_soc_dapm_route rt5660_map[] = {
	{"Speaker", NULL, "SPO"},

	{"Headset Mic", NULL, "MICBIAS1"},
	{"Headset Mic2", NULL, "MICBIAS2"},

	{"IN1P", NULL, "Headset Mic"},
	{"IN2P", NULL, "Headset Mic2"},

	{"Line Out", NULL, "LOUTL"},
	{"Line Out", NULL, "LOUTR"},

	{"DMic", NULL, "SoC DMIC"},
};

struct sof_hdmi_pcm {
	struct list_head head;
	struct snd_soc_dai *codec_dai;
	int device;
};

static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
	struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
	struct sof_hdmi_pcm *pcm;

	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
	if (!pcm)
		return -ENOMEM;

	/* dai_link id is 1:1 mapped to the PCM device */
	pcm->device = rtd->dai_link->id;
	pcm->codec_dai = dai;

	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);

	return 0;
}

static int card_late_probe(struct snd_soc_card *card)
{
	struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
	struct sof_hdmi_pcm *pcm;

	if (list_empty(&ctx->hdmi_pcm_list))
		return -ENOENT;

	if (!ctx->idisp_codec)
		return 0;

	pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);

	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
}

static int rt5660_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
	int ret;

	ret = snd_soc_dai_set_sysclk(codec_dai,
				     RT5660_SCLK_S_PLL1,
				     params_rate(params) * 512,
				     SND_SOC_CLOCK_IN);
	if (ret < 0) {
		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);

Annotation

Implementation Notes