[PATCH v4 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support

Maurizio Casciano posted 2 patches 1 month ago
There is a newer version of this series
sound/soc/intel/boards/Kconfig                |  14 +
sound/soc/intel/boards/Makefile               |   2 +
sound/soc/intel/boards/cht_rt5677.c           | 611 ++++++++++++++++++
.../intel/common/soc-acpi-intel-cht-match.c   |   8 +
4 files changed, 635 insertions(+)
create mode 100644 sound/soc/intel/boards/cht_rt5677.c
[PATCH v4 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support
Posted by Maurizio Casciano 1 month ago
The Lenovo Yoga Book YB1-X91F/L uses a Cherry Trail SSP2 link with an
RT5677 codec and a TS3A227E headset detector. Its amplifiers and
headphone path also require board-specific GPIO sequencing.

Add a generic Cherry Trail RT5677 machine driver and match the Yoga Book
ACPI codec ID. The machine entry supports both the legacy SST firmware
and the separately maintained SOF IPC3 topology.

This continues Yauhen Kharuzhy's v3 work and supersedes my RFC series.
The driver retains Yauhen's copyright and links to both his original
implementation and the v3 posting.

Changes since v3 and the RFC:

- rename the driver, file and Kconfig symbol from Yoga Book-specific
  names to generic Cherry Trail RT5677 names;
- clone the card, DAI links and link components per device instead of
  mutating global templates;
- allocate the headset jack separately with the device lifetime;
- unwind MCLK enablement on PLL or sysclk setup failures;
- document the codec ASRC clock selections;
- add the complete SST and SOF machine entry once, reducing the series
  from three ASoC patches to two; and
- carry forward Yauhen's copyright and provenance links.

The series is based on ASoC for-next at 8a070652d919. Both touched C
files passed sparse 0.6.5-rc1. Strict checkpatch reports no errors; its
only warning is the generic new-file MAINTAINERS prompt, while the
existing sound/soc/intel/ entry already covers the new driver. A clean
20-job bindeb-pkg build completed successfully.

Runtime testing used an integration kernel containing these exact v4
sources on a Lenovo Yoga Book YB1-X91L. It used the stock signed
intel/sof/sof-cht.ri firmware, version 2.2.0-57864, and the separately
maintained sof-cht-rt5677.tplg topology. The following passed:

- UCM Speaker1 and Mic1 route enablement;
- PCM0 playback and capture at 48 kHz stereo in S16_LE, S24_LE and
  S32_LE formats;
- PCM1 deep-buffer playback at 48 kHz stereo in S32_LE format;
- a bounded routed speaker tone and a non-empty three-second Mic1
  capture; and
- PipeWire playback and capture with advancing PCM pointers and clean
  PCM closure after each stream.

The GNOME Settings speaker and microphone tests also passed physical
verification. No SOF, IPC, XRUN or ASoC errors were logged during those
tests. The SOF topology source is maintained separately at:

https://github.com/Yoga-Book/Yoga-Book-Sound-Open-Firmware/commits/feature/cht-rt5677-topology2-ipc3/

Maurizio Casciano (2):
  ASoC: Intel: Add Cherry Trail RT5677 machine driver
  ASoC: Intel: cht: Add Yoga Book RT5677 machine entry

 sound/soc/intel/boards/Kconfig                |  14 +
 sound/soc/intel/boards/Makefile               |   2 +
 sound/soc/intel/boards/cht_rt5677.c           | 611 ++++++++++++++++++
 .../intel/common/soc-acpi-intel-cht-match.c   |   8 +
 4 files changed, 635 insertions(+)
 create mode 100644 sound/soc/intel/boards/cht_rt5677.c


base-commit: 8a070652d9194babdd35bf7cbd2c6722b441e8f4
-- 
2.53.0
[PATCH v5 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support
Posted by Maurizio Casciano 1 month ago
The Lenovo Yoga Book YB1-X91F/L uses a Cherry Trail SSP2 link with an
RT5677 codec and a TS3A227E headset detector. Its amplifiers and
headphone path also require board-specific GPIO sequencing.

Add a generic Cherry Trail RT5677 machine driver and match the Yoga Book
ACPI codec ID. The machine entry supports both the legacy SST firmware
and the separately maintained SOF IPC3 topology.

This continues Yauhen Kharuzhy's v3 work and supersedes my RFC series.
The driver retains Yauhen's copyright, Co-developed-by and Signed-off-by
trailers, and links to both his original implementation and v3 posting.

Changes since v4:

- restore Yauhen's Co-developed-by and immediately adjacent Signed-off-by
  trailers on both patches;
- format the complete trailer blocks without separating blank lines; and
- clear the existing PCM format mask before selecting S24_LE in the codec
  fixup, since params_set_format() is additive.

The series is based on ASoC for-next at 8a070652d919. Both touched C
files passed sparse 0.6.5-rc1. Strict checkpatch reports no errors; its
only warning is the generic new-file MAINTAINERS prompt, while the
existing sound/soc/intel/ entry already covers the driver. A clean
20-job bindeb-pkg build completed successfully.

Runtime testing used an integration kernel containing the same v5 source
state on a Lenovo Yoga Book YB1-X91L. It used the stock signed
intel/sof/sof-cht.ri firmware, version 2.2.0-57864, and the separately
maintained sof-cht-rt5677.tplg topology. The following passed:

- UCM Speaker1 and Mic1 route enablement;
- PCM0 playback and capture at 48 kHz stereo in S16_LE, S24_LE and
  S32_LE formats;
- PCM1 deep-buffer playback at 48 kHz stereo in S32_LE format;
- a bounded routed speaker tone and a non-empty three-second Mic1
  capture; and
- PipeWire playback and capture with advancing PCM pointers and clean
  PCM closure after each stream.

The GNOME Settings speaker and microphone tests also passed physical
verification. No SOF, IPC, XRUN or ASoC errors were logged during those
tests. The SOF topology source is maintained separately at:

https://github.com/Yoga-Book/Yoga-Book-Sound-Open-Firmware/commits/feature/cht-rt5677-topology2-ipc3/

Maurizio Casciano (2):
  ASoC: Intel: Add Cherry Trail RT5677 machine driver
  ASoC: Intel: cht: Add Yoga Book RT5677 machine entry

 sound/soc/intel/boards/Kconfig                |  14 +
 sound/soc/intel/boards/Makefile               |   2 +
 sound/soc/intel/boards/cht_rt5677.c           | 612 ++++++++++++++++++
 .../intel/common/soc-acpi-intel-cht-match.c   |   8 +
 4 files changed, 636 insertions(+)
 create mode 100644 sound/soc/intel/boards/cht_rt5677.c


base-commit: 8a070652d9194babdd35bf7cbd2c6722b441e8f4
-- 
2.53.0
Re: [PATCH v5 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support
Posted by Cezary Rojewski 1 month ago
On 8/27/2026 8:12 PM, Maurizio Casciano wrote:
> The Lenovo Yoga Book YB1-X91F/L uses a Cherry Trail SSP2 link with an
> RT5677 codec and a TS3A227E headset detector. Its amplifiers and
> headphone path also require board-specific GPIO sequencing.
Please do not send new revisions in response to the previous one. Also, 
please give people some time to review, especially that your patch is 
not a one-liner.

Kind regards,
Czarek
[PATCH v5 1/2] ASoC: Intel: Add Cherry Trail RT5677 machine driver
Posted by Maurizio Casciano 1 month ago
The Lenovo Yoga Book YB1-X91F/L uses the Cherry Trail SSP2 link with
an RT5677 codec and a TS3A227E headset detector. Its amplifiers and
headphone path also need board-specific GPIO sequencing.

Add a Cherry Trail RT5677 machine driver based on Yauhen Kharuzhy's
implementation. Clone the card, DAI links and link components per device
so probing never mutates global templates, and allocate jack storage with
the device lifetime. Support SST and SOF parent naming, MCLK and PLL setup,
jack buttons, microphones, and output controls.

Link: https://github.com/jekhor/yogabook-linux-kernel/commit/4e41d0ff72c1d1fd8d5c59dda247e4ca8a1da999
Link: https://lore.kernel.org/linux-sound/20260611-asoc-yogabook-v2-v3-3-3128447b67b6@gmail.com/
Assisted-by: Codex:gpt-5.6-sol sparse
Co-developed-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>
---
 sound/soc/intel/boards/Kconfig      |  14 +
 sound/soc/intel/boards/Makefile     |   2 +
 sound/soc/intel/boards/cht_rt5677.c | 612 ++++++++++++++++++++++++++++
 3 files changed, 628 insertions(+)
 create mode 100644 sound/soc/intel/boards/cht_rt5677.c

diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index cddbd2aa424e..33b2b409f150 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -161,6 +161,20 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
 	  Say Y or m if you have such a device. This is a recommended option.
 	  If unsure select "N".
 
+config SND_SOC_INTEL_CHT_RT5677_MACH
+	tristate "Cherrytrail with RT5677 codec"
+	depends on I2C && ACPI
+	depends on X86_INTEL_LPSS || COMPILE_TEST
+	depends on GPIOLIB || COMPILE_TEST
+	select SND_SOC_ACPI
+	select SND_SOC_RT5677
+	select SND_SOC_TS3A227E
+	help
+	  This adds support for Cherry Trail platforms with an RT5677 codec
+	  and TS3A227E headset-jack detector. It currently supports the
+	  Lenovo Yoga Book YB1-X91F/L.
+	  Say Y or m if you have such a device. If unsure select "N".
+
 config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
 	tristate "Cherrytrail & Braswell with RT5645/5650 codec"
 	depends on I2C && ACPI
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 25a1a9066cbf..28940ca02aa7 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -9,6 +9,7 @@ snd-soc-sst-bytcr-rt5640-y := bytcr_rt5640.o
 snd-soc-sst-bytcr-rt5651-y := bytcr_rt5651.o
 snd-soc-sst-bytcr-wm5102-y := bytcr_wm5102.o
 snd-soc-sst-cht-bsw-rt5672-y := cht_bsw_rt5672.o
+snd-soc-sst-cht-rt5677-y := cht_rt5677.o
 snd-soc-sst-cht-bsw-rt5645-y := cht_bsw_rt5645.o
 snd-soc-sst-cht-bsw-max98090_ti-y := cht_bsw_max98090_ti.o
 snd-soc-sst-cht-bsw-nau8824-y := cht_bsw_nau8824.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
 obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
 obj-$(CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH) += snd-soc-sst-bytcr-wm5102.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
+obj-$(CONFIG_SND_SOC_INTEL_CHT_RT5677_MACH) += snd-soc-sst-cht-rt5677.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH) += snd-soc-sst-cht-bsw-nau8824.o
diff --git a/sound/soc/intel/boards/cht_rt5677.c b/sound/soc/intel/boards/cht_rt5677.c
new file mode 100644
index 000000000000..bb91693e41d7
--- /dev/null
+++ b/sound/soc/intel/boards/cht_rt5677.c
@@ -0,0 +1,612 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  cht_rt5677.c - ASoC machine driver for Cherry Trail with RT5677
+ *
+ *  Copyright (C) 2026 Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ *  Based on the mainline cht_bsw_rt5672.c driver and Lenovo's
+ *  cht_bl_dpcm_rt5677.c Android driver.
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "../../codecs/rt5677.h"
+#include "../../codecs/ts3a227e.h"
+#include "../atom/sst-atom-controls.h"
+
+#define RT5677_I2C	"i2c-rt5677"
+
+/* Platform clock 3 provides the codec's 19.2 MHz I2S master clock. */
+#define CHT_PLAT_CLK_3_HZ	19200000
+#define CHT_CODEC_DAI	"rt5677-aif1"
+
+struct cht_rt5677_private {
+	char codec_name[SND_ACPI_I2C_ID_LEN];
+	struct clk *mclk;
+	struct gpio_desc *gpio_spk_en1;
+	struct gpio_desc *gpio_spk_en2;
+	struct gpio_desc *gpio_hp_en;
+};
+
+static int cht_rt5677_platform_clock_enable(struct snd_soc_card *card,
+					    struct snd_soc_dai *codec_dai)
+{
+	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	ret = clk_prepare_enable(ctx->mclk);
+	if (ret) {
+		dev_err(card->dev, "enabling MCLK failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5677_PLL1_S_MCLK,
+				  CHT_PLAT_CLK_3_HZ, 48000 * 512);
+	if (ret) {
+		dev_err(card->dev, "setting codec PLL failed: %d\n", ret);
+		goto disable_mclk;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_PLL1,
+				     48000 * 512, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(card->dev, "setting codec sysclk failed: %d\n", ret);
+		goto disable_mclk;
+	}
+
+	return 0;
+
+disable_mclk:
+	clk_disable_unprepare(ctx->mclk);
+	return ret;
+}
+
+static void cht_rt5677_platform_clock_disable(struct snd_soc_card *card,
+					      struct snd_soc_dai *codec_dai)
+{
+	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_RCCLK,
+				     48000 * 512, SND_SOC_CLOCK_IN);
+	if (ret)
+		dev_warn(card->dev, "setting codec idle sysclk failed: %d\n", ret);
+
+	clk_disable_unprepare(ctx->mclk);
+}
+
+static int cht_rt5677_platform_clock_control(struct snd_soc_dapm_widget *w,
+					     struct snd_kcontrol *kctl,
+					     int event)
+{
+	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
+	struct snd_soc_dai *codec_dai;
+
+	codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI);
+	if (!codec_dai) {
+		dev_err(card->dev, "codec DAI not found\n");
+		return -EIO;
+	}
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		return cht_rt5677_platform_clock_enable(card, codec_dai);
+
+	cht_rt5677_platform_clock_disable(card, codec_dai);
+
+	return 0;
+}
+
+static int cht_rt5677_hp_event(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kctl, int event)
+{
+	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
+	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
+
+	gpiod_set_value_cansleep(ctx->gpio_hp_en, SND_SOC_DAPM_EVENT_ON(event));
+
+	return 0;
+}
+
+static int cht_rt5677_spk_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kctl, int event)
+{
+	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
+	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
+
+	gpiod_set_value_cansleep(ctx->gpio_spk_en1, SND_SOC_DAPM_EVENT_ON(event));
+	gpiod_set_value_cansleep(ctx->gpio_spk_en2, SND_SOC_DAPM_EVENT_ON(event));
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget cht_rt5677_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", cht_rt5677_hp_event),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+	SND_SOC_DAPM_SPK("Speaker", cht_rt5677_spk_event),
+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+			    cht_rt5677_platform_clock_control,
+			    SND_SOC_DAPM_PRE_PMU |
+			    SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route cht_rt5677_map[] = {
+	{"IN1P", NULL, "Headset Mic"},
+	{"IN1N", NULL, "Headset Mic"},
+	{"DMIC L1", NULL, "Int Mic"},
+	{"DMIC R1", NULL, "Int Mic"},
+	{"Headphone", NULL, "LOUT1"},
+	{"Headphone", NULL, "LOUT2"},
+	{"Speaker", NULL, "LOUT1"},
+	{"Speaker", NULL, "LOUT2"},
+
+	{"AIF1 Playback", NULL, "ssp2 Tx"},
+	{"ssp2 Tx", NULL, "codec_out0"},
+	{"ssp2 Tx", NULL, "codec_out1"},
+	{"codec_in0", NULL, "ssp2 Rx"},
+	{"codec_in1", NULL, "ssp2 Rx"},
+	{"ssp2 Rx", NULL, "AIF1 Capture"},
+	{"Headphone", NULL, "Platform Clock"},
+	{"Speaker", NULL, "Platform Clock"},
+	{"Headset Mic", NULL, "Platform Clock"},
+	{"Int Mic", NULL, "Platform Clock"},
+};
+
+static const struct snd_kcontrol_new cht_rt5677_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+	SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+static int cht_rt5677_aif1_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+	int ret;
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5677_PLL1_S_MCLK,
+				  CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
+	if (ret) {
+		dev_err(rtd->dev, "setting codec PLL failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_PLL1,
+				     params_rate(params) * 512,
+				     SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->dev, "setting codec sysclk failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_fmt(codec_dai,
+				  SND_SOC_DAIFMT_DSP_B |
+				  SND_SOC_DAIFMT_IB_NF |
+				  SND_SOC_DAIFMT_CBC_CFC);
+	if (ret) {
+		dev_err(codec_dai->dev, "setting TDM format failed: %d\n", ret);
+		return ret;
+	}
+
+	/* Four 25-bit DSP_B slots carry 24-bit samples; the codec uses slots 0 and 1. */
+	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 4, 25);
+	if (ret) {
+		dev_err(rtd->dev, "setting codec TDM slots failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cht_rt5677_codec_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0);
+	struct snd_soc_component *component = codec_dai->component;
+	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(runtime->card);
+	int ret;
+
+	/*
+	 * The codec derives its asynchronous sample-rate conversion clocks from
+	 * I2S1 while the SSP link runs from the Cherry Trail platform clock.
+	 */
+	rt5677_sel_asrc_clk_src(component, RT5677_DA_STEREO_FILTER |
+					    RT5677_AD_STEREO1_FILTER |
+					    RT5677_I2S1_SOURCE,
+				     RT5677_CLK_SEL_I2S1_ASRC);
+
+	/* Mono ADC L uses the codec system clock rather than the I2S1 clock. */
+	rt5677_sel_asrc_clk_src(component, RT5677_AD_MONO_L_FILTER, RT5677_CLK_SEL_SYS2);
+
+	/* Firmware may leave MCLK enabled without updating the CCF count. */
+	ret = clk_prepare_enable(ctx->mclk);
+	if (ret) {
+		dev_err(runtime->dev, "preparing MCLK failed: %d\n", ret);
+		return ret;
+	}
+	clk_disable_unprepare(ctx->mclk);
+
+	ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
+	if (ret) {
+		dev_err(runtime->dev, "setting MCLK rate failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cht_rt5677_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+				  struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+						SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* The DSP will convert the FE rate to 48k, stereo, 24bits */
+	rate->min = 48000;
+	rate->max = 48000;
+	channels->min = 2;
+	channels->max = 2;
+
+	/*
+	 * Configure SSP2 for the 24-bit format expected by the codec. The SST
+	 * ssp2-port front end still advertises S16_LE and converts the stream.
+	 */
+	snd_mask_none(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT));
+	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+	return 0;
+}
+
+static struct snd_soc_jack_pin cht_rt5677_jack_pins[] = {
+	{
+		.pin = "Headphone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
+static int cht_rt5677_headset_init(struct snd_soc_component *component)
+{
+	struct snd_soc_card *card = component->card;
+	struct snd_soc_jack *jack;
+	int jack_type;
+	int ret;
+
+	jack = devm_kzalloc(card->dev, sizeof(*jack), GFP_KERNEL);
+	if (!jack)
+		return -ENOMEM;
+
+	/*
+	 * TI supports four headset buttons:
+	 * KEY_MEDIA
+	 * KEY_VOICECOMMAND
+	 * KEY_VOLUMEUP
+	 * KEY_VOLUMEDOWN
+	 */
+	jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
+		    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+		    SND_JACK_BTN_2 | SND_JACK_BTN_3;
+
+	ret = snd_soc_card_jack_new_pins(card, "Headset Jack", jack_type,
+					 jack, cht_rt5677_jack_pins,
+					 ARRAY_SIZE(cht_rt5677_jack_pins));
+	if (ret) {
+		dev_err(card->dev, "creating headset jack failed: %d\n", ret);
+		return ret;
+	}
+
+	return ts3a227e_enable_jack_detect(component, jack);
+}
+
+static int cht_rt5677_aif1_startup(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_hw_constraint_single(substream->runtime,
+			SNDRV_PCM_HW_PARAM_RATE, 48000);
+}
+
+static const struct snd_soc_ops cht_rt5677_aif1_ops = {
+	.startup = cht_rt5677_aif1_startup,
+};
+
+static const struct snd_soc_ops cht_rt5677_be_ssp2_ops = {
+	.hw_params = cht_rt5677_aif1_hw_params,
+};
+
+static const struct snd_soc_aux_dev cht_rt5677_headset_dev = {
+	.dlc = COMP_AUX("i2c-ts3a227e"),
+	.init = cht_rt5677_headset_init,
+};
+
+SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(media, DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(deepbuffer, DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(ssp2_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
+SND_SOC_DAILINK_DEF(ssp2_codec, DAILINK_COMP_ARRAY(COMP_CODEC(RT5677_I2C, CHT_CODEC_DAI)));
+
+SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
+
+static const struct snd_soc_dai_link cht_rt5677_dailink[] = {
+	/* Front End DAI links */
+	[MERR_DPCM_AUDIO] = {
+		.name = "Audio Port",
+		.stream_name = "Audio",
+		.nonatomic = true,
+		.dynamic = 1,
+		.ops = &cht_rt5677_aif1_ops,
+		SND_SOC_DAILINK_REG(media, dummy, platform),
+	},
+	[MERR_DPCM_DEEP_BUFFER] = {
+		.name = "Deep-Buffer Audio Port",
+		.stream_name = "Deep-Buffer Audio",
+		.nonatomic = true,
+		.dynamic = 1,
+		.playback_only = 1,
+		.ops = &cht_rt5677_aif1_ops,
+		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
+	},
+
+	/* Back End DAI links */
+	{
+		/* SSP2 - Codec */
+		.name = "SSP2-Codec",
+		.id = 0,
+		.no_pcm = 1,
+		.nonatomic = true,
+		.init = cht_rt5677_codec_init,
+		.be_hw_params_fixup = cht_rt5677_codec_fixup,
+		.ops = &cht_rt5677_be_ssp2_ops,
+		SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+	},
+};
+
+/* SoC card */
+static const struct snd_soc_card cht_rt5677_card = {
+	.owner = THIS_MODULE,
+	.num_links = ARRAY_SIZE(cht_rt5677_dailink),
+	.num_aux_devs = 1,
+	.dapm_widgets = cht_rt5677_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(cht_rt5677_widgets),
+	.dapm_routes = cht_rt5677_map,
+	.num_dapm_routes = ARRAY_SIZE(cht_rt5677_map),
+	.controls = cht_rt5677_controls,
+	.num_controls = ARRAY_SIZE(cht_rt5677_controls),
+};
+
+static const struct acpi_gpio_params speaker_enable_gpio = { 2, 0, false };
+static const struct acpi_gpio_mapping cht_rt5677_gpios[] = {
+	{ "speaker-enable-gpios", &speaker_enable_gpio, 1 },
+	{ }
+};
+
+#define SOF_CARD_NAME "cht yogabook"
+#define SOF_DRIVER_NAME "SOF"
+
+#define CARD_NAME "cht-rt5677"
+#define DRIVER_NAME NULL
+
+static void cht_rt5677_gpiod_put(void *data)
+{
+	gpiod_put(data);
+}
+
+static void cht_rt5677_remove_driver_gpios(void *data)
+{
+	acpi_dev_remove_driver_gpios(data);
+}
+
+static int cht_rt5677_get_gpio(struct device *dev, struct device *codec_dev,
+			       const char *con_id, struct gpio_desc **gpio)
+{
+	int ret;
+
+	*gpio = gpiod_get(codec_dev, con_id, GPIOD_OUT_LOW);
+	if (IS_ERR(*gpio)) {
+		ret = PTR_ERR(*gpio);
+		return dev_err_probe(dev, ret, "getting %s GPIO failed\n", con_id);
+	}
+
+	ret = devm_add_action_or_reset(dev, cht_rt5677_gpiod_put, *gpio);
+	if (ret)
+		return dev_err_probe(dev, ret, "registering %s GPIO cleanup failed\n",
+				     con_id);
+
+	return 0;
+}
+
+static int cht_rt5677_clone_dai_links(struct device *dev, struct snd_soc_card *card)
+{
+	struct snd_soc_dai_link_component *components;
+	struct snd_soc_dai_link *links;
+	size_t size;
+	int i;
+
+	links = devm_kmemdup(dev, cht_rt5677_dailink,
+			     sizeof(cht_rt5677_dailink), GFP_KERNEL);
+	if (!links)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(cht_rt5677_dailink); i++) {
+		if (links[i].num_cpus) {
+			size = sizeof(*components) * links[i].num_cpus;
+			components = devm_kmemdup(dev, links[i].cpus, size, GFP_KERNEL);
+			if (!components)
+				return -ENOMEM;
+			links[i].cpus = components;
+		}
+
+		if (links[i].num_codecs) {
+			size = sizeof(*components) * links[i].num_codecs;
+			components = devm_kmemdup(dev, links[i].codecs, size, GFP_KERNEL);
+			if (!components)
+				return -ENOMEM;
+			links[i].codecs = components;
+		}
+
+		if (links[i].num_platforms) {
+			size = sizeof(*components) * links[i].num_platforms;
+			components = devm_kmemdup(dev, links[i].platforms, size, GFP_KERNEL);
+			if (!components)
+				return -ENOMEM;
+			links[i].platforms = components;
+		}
+	}
+
+	card->dai_link = links;
+	return 0;
+}
+
+static int snd_cht_rt5677_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cht_rt5677_private *ctx;
+	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
+	struct snd_soc_aux_dev *aux_dev;
+	struct snd_soc_dai_link *dai_links;
+	struct snd_soc_card *card;
+	const char *platform_name;
+	struct acpi_device *adev;
+	struct device *codec_dev;
+	bool sof_parent;
+	int ret;
+	int i;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	card = devm_kmemdup(dev, &cht_rt5677_card, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	ret = cht_rt5677_clone_dai_links(dev, card);
+	if (ret)
+		return ret;
+	dai_links = card->dai_link;
+
+	aux_dev = devm_kmemdup(dev, &cht_rt5677_headset_dev,
+			       sizeof(cht_rt5677_headset_dev), GFP_KERNEL);
+	if (!aux_dev)
+		return -ENOMEM;
+
+	card->aux_dev = aux_dev;
+
+	strscpy(ctx->codec_name, RT5677_I2C, sizeof(ctx->codec_name));
+
+	/* Use the ACPI-enumerated codec name when firmware describes the codec. */
+	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+	if (adev) {
+		snprintf(ctx->codec_name, sizeof(ctx->codec_name),
+			 "i2c-%s", acpi_dev_name(adev));
+
+		acpi_dev_put(adev);
+		for (i = 0; i < card->num_links; i++) {
+			if (dai_links[i].codecs->name &&
+			    !strcmp(dai_links[i].codecs->name,
+				    RT5677_I2C)) {
+				dai_links[i].codecs->name = ctx->codec_name;
+				break;
+			}
+		}
+	}
+
+	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
+					    ctx->codec_name);
+	if (!codec_dev)
+		return dev_err_probe(dev, -EPROBE_DEFER,
+				     "waiting for codec %s\n", ctx->codec_name);
+
+	adev = ACPI_COMPANION(codec_dev);
+	if (adev) {
+		ret = acpi_dev_add_driver_gpios(adev, cht_rt5677_gpios);
+		if (ret) {
+			dev_err_probe(dev, ret, "adding codec GPIO mappings failed\n");
+			goto out_put_codec;
+		}
+
+		ret = devm_add_action_or_reset(dev, cht_rt5677_remove_driver_gpios, adev);
+		if (ret) {
+			dev_err_probe(dev, ret, "registering GPIO mapping cleanup failed\n");
+			goto out_put_codec;
+		}
+	}
+
+	ret = cht_rt5677_get_gpio(dev, codec_dev, "speaker-enable", &ctx->gpio_spk_en1);
+	if (ret)
+		goto out_put_codec;
+
+	ret = cht_rt5677_get_gpio(dev, codec_dev, "speaker-enable2", &ctx->gpio_spk_en2);
+	if (ret)
+		goto out_put_codec;
+
+	ret = cht_rt5677_get_gpio(dev, codec_dev, "headphone-enable", &ctx->gpio_hp_en);
+	if (ret)
+		goto out_put_codec;
+
+	put_device(codec_dev);
+
+	card->dev = dev;
+	platform_name = mach->mach_params.platform;
+
+	ret = snd_soc_fixup_dai_links_platform_name(card, platform_name);
+	if (ret)
+		return dev_err_probe(dev, ret, "fixing DAI link platform name failed\n");
+
+	ctx->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
+	if (IS_ERR(ctx->mclk))
+		return dev_err_probe(dev, PTR_ERR(ctx->mclk), "getting MCLK failed\n");
+
+	snd_soc_card_set_drvdata(card, ctx);
+
+	sof_parent = snd_soc_acpi_sof_parent(dev);
+
+	if (sof_parent) {
+		card->name = SOF_CARD_NAME;
+		card->driver_name = SOF_DRIVER_NAME;
+	} else {
+		card->name = CARD_NAME;
+		card->driver_name = DRIVER_NAME;
+	}
+
+	ret = devm_snd_soc_register_card(dev, card);
+	if (ret)
+		return dev_err_probe(dev, ret, "registering sound card failed\n");
+
+	return 0;
+
+out_put_codec:
+	put_device(codec_dev);
+	return ret;
+}
+
+static struct platform_driver snd_cht_rt5677_driver = {
+	.driver = {
+		.name = "cht-rt5677",
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = snd_cht_rt5677_probe,
+};
+
+module_platform_driver(snd_cht_rt5677_driver);
+
+MODULE_DESCRIPTION("Cherry Trail RT5677 machine driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cht-rt5677");
-- 
2.53.0
Re: [PATCH v5 1/2] ASoC: Intel: Add Cherry Trail RT5677 machine driver
Posted by Cezary Rojewski 3 weeks, 4 days ago
On 8/27/2026 8:12 PM, Maurizio Casciano wrote:
> The Lenovo Yoga Book YB1-X91F/L uses the Cherry Trail SSP2 link with
> an RT5677 codec and a TS3A227E headset detector. Its amplifiers and
> headphone path also need board-specific GPIO sequencing.
> 
> Add a Cherry Trail RT5677 machine driver based on Yauhen Kharuzhy's
> implementation. Clone the card, DAI links and link components per device
> so probing never mutates global templates, and allocate jack storage with
> the device lifetime. Support SST and SOF parent naming, MCLK and PLL setup,
> jack buttons, microphones, and output controls.
> 
> Link: https://github.com/jekhor/yogabook-linux-kernel/commit/4e41d0ff72c1d1fd8d5c59dda247e4ca8a1da999
> Link: https://lore.kernel.org/linux-sound/20260611-asoc-yogabook-v2-v3-3-3128447b67b6@gmail.com/
> Assisted-by: Codex:gpt-5.6-sol sparse
> Co-developed-by: Yauhen Kharuzhy <jekhor@gmail.com>
> Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
> Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>

Looks better, a bit of work and we have a merge candidate.

> +static void cht_rt5677_platform_clock_disable(struct snd_soc_card *card,
> +					      struct snd_soc_dai *codec_dai)
> +{
> +	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
> +	int ret;
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_RCCLK,
> +				     48000 * 512, SND_SOC_CLOCK_IN);
> +	if (ret)
> +		dev_warn(card->dev, "setting codec idle sysclk failed: %d\n", ret);
> +
> +	clk_disable_unprepare(ctx->mclk);
> +}
> +
> +static int cht_rt5677_platform_clock_control(struct snd_soc_dapm_widget *w,
> +					     struct snd_kcontrol *kctl,
> +					     int event)
> +{
> +	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
> +	struct snd_soc_dai *codec_dai;
> +
> +	codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI);
> +	if (!codec_dai) {
> +		dev_err(card->dev, "codec DAI not found\n");
> +		return -EIO;
> +	}
> +
> +	if (SND_SOC_DAPM_EVENT_ON(event))
> +		return cht_rt5677_platform_clock_enable(card, codec_dai);
> +
> +	cht_rt5677_platform_clock_disable(card, codec_dai);
> +
> +	return 0;

I believe clock_control(event=disable) should not be ignoring result of
cht_rt5677_platform_clock_disable().  Yeah, currently the function
returns void but with small update, this could be corrected.  In
general, the right approach is based on the use-case - teardown path
invoked during error handling should be persmissive.  Conscious disable
operation (here, clock control) I believe shall not.

> +}
> +
> +static int cht_rt5677_hp_event(struct snd_soc_dapm_widget *w,
> +			       struct snd_kcontrol *kctl, int event)
> +{
> +	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
> +	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
> +
> +	gpiod_set_value_cansleep(ctx->gpio_hp_en, SND_SOC_DAPM_EVENT_ON(event));
> +
> +	return 0;

gpiod_set_value_cansleep() can fail and blind "return 0" is discouraged.

> +}
> +
> +static int cht_rt5677_spk_event(struct snd_soc_dapm_widget *w,
> +				struct snd_kcontrol *kctl, int event)
> +{
> +	struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
> +	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(card);
> +
> +	gpiod_set_value_cansleep(ctx->gpio_spk_en1, SND_SOC_DAPM_EVENT_ON(event));
> +	gpiod_set_value_cansleep(ctx->gpio_spk_en2, SND_SOC_DAPM_EVENT_ON(event));
> +
> +	return 0;

Ditto.

> +static int cht_rt5677_codec_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0);
> +	struct snd_soc_component *component = codec_dai->component;
> +	struct cht_rt5677_private *ctx = snd_soc_card_get_drvdata(runtime->card);
> +	int ret;
> +
> +	/*
> +	 * The codec derives its asynchronous sample-rate conversion clocks from
> +	 * I2S1 while the SSP link runs from the Cherry Trail platform clock.
> +	 */
> +	rt5677_sel_asrc_clk_src(component, RT5677_DA_STEREO_FILTER |
> +					    RT5677_AD_STEREO1_FILTER |
> +					    RT5677_I2S1_SOURCE,
> +				     RT5677_CLK_SEL_I2S1_ASRC);

Please do not ignore the result of rt5677_sel_asrc_clk_src().

> +
> +	/* Mono ADC L uses the codec system clock rather than the I2S1 clock. */
> +	rt5677_sel_asrc_clk_src(component, RT5677_AD_MONO_L_FILTER, RT5677_CLK_SEL_SYS2);

Ditto.

> +
> +	/* Firmware may leave MCLK enabled without updating the CCF count. */
> +	ret = clk_prepare_enable(ctx->mclk);
> +	if (ret) {
> +		dev_err(runtime->dev, "preparing MCLK failed: %d\n", ret);
> +		return ret;
> +	}
> +	clk_disable_unprepare(ctx->mclk);
> +
> +	ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
> +	if (ret) {
> +		dev_err(runtime->dev, "setting MCLK rate failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}

> +SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
> +
> +SND_SOC_DAILINK_DEF(media, DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
> +
> +SND_SOC_DAILINK_DEF(deepbuffer, DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
> +
> +SND_SOC_DAILINK_DEF(ssp2_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
> +SND_SOC_DAILINK_DEF(ssp2_codec, DAILINK_COMP_ARRAY(COMP_CODEC(RT5677_I2C, CHT_CODEC_DAI)));
> +
> +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));

I'd suggest to drop the newlines between SND_SOC_DAILINK_DEF entries.
Perhaps also have a tab(s) instead of a space before DAILINK_COMP_ARRAY
so all the definitions are aligned nicely.

> +
> +static const struct snd_soc_dai_link cht_rt5677_dailink[] = {
> +	/* Front End DAI links */
> +	[MERR_DPCM_AUDIO] = {
> +		.name = "Audio Port",
> +		.stream_name = "Audio",
> +		.nonatomic = true,
> +		.dynamic = 1,
> +		.ops = &cht_rt5677_aif1_ops,
> +		SND_SOC_DAILINK_REG(media, dummy, platform),
> +	},
> +	[MERR_DPCM_DEEP_BUFFER] = {
> +		.name = "Deep-Buffer Audio Port",
> +		.stream_name = "Deep-Buffer Audio",

Did you test both endpoints, the low-latency and the high-latency one?
While I did not touch atom-driver really, when refactoring its sibling
(now called catpt-driver) I had to do quite a bit of tinkering to verify
the high-latency playback path actually works.

> +		.nonatomic = true,
> +		.dynamic = 1,
> +		.playback_only = 1,
> +		.ops = &cht_rt5677_aif1_ops,
> +		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
> +	},
> +
> +	/* Back End DAI links */
> +	{
> +		/* SSP2 - Codec */
> +		.name = "SSP2-Codec",
> +		.id = 0,
> +		.no_pcm = 1,
> +		.nonatomic = true,
> +		.init = cht_rt5677_codec_init,
> +		.be_hw_params_fixup = cht_rt5677_codec_fixup,
> +		.ops = &cht_rt5677_be_ssp2_ops,
> +		SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
> +	},
> +};
> +
> +/* SoC card */

The comment is redundant.

> +static const struct snd_soc_card cht_rt5677_card = {
> +	.owner = THIS_MODULE,
> +	.num_links = ARRAY_SIZE(cht_rt5677_dailink),
> +	.num_aux_devs = 1,
> +	.dapm_widgets = cht_rt5677_widgets,
> +	.num_dapm_widgets = ARRAY_SIZE(cht_rt5677_widgets),
> +	.dapm_routes = cht_rt5677_map,
> +	.num_dapm_routes = ARRAY_SIZE(cht_rt5677_map),
> +	.controls = cht_rt5677_controls,
> +	.num_controls = ARRAY_SIZE(cht_rt5677_controls),
> +};
> +
> +static const struct acpi_gpio_params speaker_enable_gpio = { 2, 0, false };
> +static const struct acpi_gpio_mapping cht_rt5677_gpios[] = {
> +	{ "speaker-enable-gpios", &speaker_enable_gpio, 1 },
> +	{ }
> +};
> +
> +#define SOF_CARD_NAME "cht yogabook"
> +#define SOF_DRIVER_NAME "SOF"
> +
> +#define CARD_NAME "cht-rt5677"
> +#define DRIVER_NAME NULL

I'm going to repeat myself from v2 [1]:

Have you tested the driver with both, legacy -and- SOF firmware? If
you're using just one of them, let's limit the driver to that one.
Anything else can be part of a follow up series if there is a need to
support multiple solutions. Otherwise we'd be merging code with no
coverage and no user.

[1]:
https://lore.kernel.org/all/7932c58b-b6fa-40c3-8967-7710d84f9667@intel.com/

> +static int snd_cht_rt5677_probe(struct platform_device *pdev)

> +
> +	card->dev = dev;
> +	platform_name = mach->mach_params.platform;
> +
> +	ret = snd_soc_fixup_dai_links_platform_name(card, platform_name);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "fixing DAI link platform name failed\n");

Could you run a test without snd_soc_fixup_dai_links_platform_name() ?
The function is more of a relict of the past.
[PATCH v5 2/2] ASoC: Intel: cht: Add Yoga Book RT5677 machine entry
Posted by Maurizio Casciano 1 month ago
The Yoga Book YB1-X91F/L exposes its RT5677 codec as ACPI device
10EC5677. Add a Cherry Trail machine-table entry so SST creates the
cht-rt5677 machine device and loads intel/fw_sst_22a8.bin.

Associate the same entry with sof-cht-rt5677.tplg so SOF loads the
matching IPC3 topology through the standard firmware search path. The
topology sources are maintained and distributed separately by the SOF
project.

Assisted-by: Codex:gpt-5.6-sol sparse
Co-developed-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>
---
 sound/soc/intel/common/soc-acpi-intel-cht-match.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index e4c3492a0c28..442ef30ffcc7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -137,6 +137,14 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_cherrytrail_machines[] = {
 		.board = "cht-bsw",
 		.sof_tplg_filename = "sof-cht-rt5670.tplg",
 	},
+	{
+		/* Lenovo Yoga Book YB1-X91F/L */
+		.id = "10EC5677",
+		.drv_name = "cht-rt5677",
+		.fw_filename = "intel/fw_sst_22a8.bin",
+		.board = "cht_rt5677",
+		.sof_tplg_filename = "sof-cht-rt5677.tplg",
+	},
 	{
 		.comp_ids = &rt5645_comp_ids,
 		.drv_name = "cht-bsw-rt5645",
-- 
2.53.0
Re: [PATCH v4 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support
Posted by Yauhen Kharuzhy 1 month ago
Hi Maurizio,

I am glad to see my (a bit abandoned) work to have YB1-X9* support in
mainline be continued but please don't drop
my ownership for patches when using them. Use Co-developed-by: to
mention me as co-developer
and keep my Signed-off-by: tags.

For reference, my WiP v4 tree is here:
https://github.com/jekhor/yogabook-linux-kernel/commits/b4/asoc-yogabook-v4/

чт, 27 авг. 2026 г. в 10:25, Maurizio Casciano <mauriziocasciano7@gmail.com>:
>
> The Lenovo Yoga Book YB1-X91F/L uses a Cherry Trail SSP2 link with an
> RT5677 codec and a TS3A227E headset detector. Its amplifiers and
> headphone path also require board-specific GPIO sequencing.
>
> Add a generic Cherry Trail RT5677 machine driver and match the Yoga Book
> ACPI codec ID. The machine entry supports both the legacy SST firmware
> and the separately maintained SOF IPC3 topology.
>
> This continues Yauhen Kharuzhy's v3 work and supersedes my RFC series.
> The driver retains Yauhen's copyright and links to both his original
> implementation and the v3 posting.
>
> Changes since v3 and the RFC:
>
> - rename the driver, file and Kconfig symbol from Yoga Book-specific
>   names to generic Cherry Trail RT5677 names;
> - clone the card, DAI links and link components per device instead of
>   mutating global templates;
> - allocate the headset jack separately with the device lifetime;
> - unwind MCLK enablement on PLL or sysclk setup failures;
> - document the codec ASRC clock selections;
> - add the complete SST and SOF machine entry once, reducing the series
>   from three ASoC patches to two; and
> - carry forward Yauhen's copyright and provenance links.
>
> The series is based on ASoC for-next at 8a070652d919. Both touched C
> files passed sparse 0.6.5-rc1. Strict checkpatch reports no errors; its
> only warning is the generic new-file MAINTAINERS prompt, while the
> existing sound/soc/intel/ entry already covers the new driver. A clean
> 20-job bindeb-pkg build completed successfully.
>
> Runtime testing used an integration kernel containing these exact v4
> sources on a Lenovo Yoga Book YB1-X91L. It used the stock signed
> intel/sof/sof-cht.ri firmware, version 2.2.0-57864, and the separately
> maintained sof-cht-rt5677.tplg topology. The following passed:
>
> - UCM Speaker1 and Mic1 route enablement;
> - PCM0 playback and capture at 48 kHz stereo in S16_LE, S24_LE and
>   S32_LE formats;
> - PCM1 deep-buffer playback at 48 kHz stereo in S32_LE format;
> - a bounded routed speaker tone and a non-empty three-second Mic1
>   capture; and
> - PipeWire playback and capture with advancing PCM pointers and clean
>   PCM closure after each stream.
>
> The GNOME Settings speaker and microphone tests also passed physical
> verification. No SOF, IPC, XRUN or ASoC errors were logged during those
> tests. The SOF topology source is maintained separately at:
>
> https://github.com/Yoga-Book/Yoga-Book-Sound-Open-Firmware/commits/feature/cht-rt5677-topology2-ipc3/
>
> Maurizio Casciano (2):
>   ASoC: Intel: Add Cherry Trail RT5677 machine driver
>   ASoC: Intel: cht: Add Yoga Book RT5677 machine entry
>
>  sound/soc/intel/boards/Kconfig                |  14 +
>  sound/soc/intel/boards/Makefile               |   2 +
>  sound/soc/intel/boards/cht_rt5677.c           | 611 ++++++++++++++++++
>  .../intel/common/soc-acpi-intel-cht-match.c   |   8 +
>  4 files changed, 635 insertions(+)
>  create mode 100644 sound/soc/intel/boards/cht_rt5677.c
>
>
> base-commit: 8a070652d9194babdd35bf7cbd2c6722b441e8f4
> --
> 2.53.0



-- 
Yauhen Kharuzhy
Re: [PATCH v4 0/2] ASoC: Intel: Add Lenovo Yoga Book RT5677 support
Posted by Maurizio Casciano 1 month ago
You are right, and I am sorry for dropping your ownership trailers in v4.

Both v5 patches now retain your Co-developed-by immediately followed by your
Signed-off-by, in addition to your copyright and the links to your original
implementation and v3 posting. You are also CC'd on the complete v5 series.

Thank you for continuing to help with this work.

Maurizio