* [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41
@ 2025-06-12 16:00 Stefan Binding
2025-06-12 16:00 ` [PATCH v1 1/2] ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA Stefan Binding
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Stefan Binding @ 2025-06-12 16:00 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel, patches, Stefan Binding
Add support for 1 amp configuration for ASUS NUC using CS35L41.
The NUC is using 1 CS35L41 amplifier using SPI with Internal Boost.
Stefan Binding (2):
ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA
ALSA: hda/realtek: Add support for ASUS NUC using CS35L41 HDA
include/sound/cs35l41.h | 12 ++++
sound/pci/hda/cs35l41_hda.c | 103 +++++++++++++++++++++-------------
sound/pci/hda/cs35l41_hda.h | 1 +
sound/pci/hda/patch_realtek.c | 11 ++++
4 files changed, 89 insertions(+), 38 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 1/2] ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA
2025-06-12 16:00 [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Stefan Binding
@ 2025-06-12 16:00 ` Stefan Binding
2025-06-12 16:00 ` [PATCH v1 2/2] ALSA: hda/realtek: Add support for ASUS NUC using " Stefan Binding
2025-06-13 8:20 ` [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Takashi Iwai
2 siblings, 0 replies; 4+ messages in thread
From: Stefan Binding @ 2025-06-12 16:00 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel, patches, Stefan Binding
Currently only left and right channels are supported for each amp.
Support is needed for a center channel, using both left and right
channel audio.
Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
---
include/sound/cs35l41.h | 12 +++++
sound/pci/hda/cs35l41_hda.c | 103 +++++++++++++++++++++++-------------
sound/pci/hda/cs35l41_hda.h | 1 +
3 files changed, 78 insertions(+), 38 deletions(-)
diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 43c6a9ef8d9f..7542cabfa726 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -609,6 +609,18 @@
#define CS35L41_DSP_NG_DELAY_MASK 0x0F00
#define CS35L41_DSP_NG_DELAY_SHIFT 8
+#define CS35L41_ASP_RX1_EN_MASK 0x00010000
+#define CS35L41_ASP_RX1_EN_SHIFT 16
+#define CS35L41_ASP_RX2_EN_MASK 0x00020000
+#define CS35L41_ASP_RX2_EN_SHIFT 17
+#define CS35L41_ASP_TX1_EN_MASK 0x00000001
+#define CS35L41_ASP_TX1_EN_SHIFT 0
+#define CS35L41_ASP_TX2_EN_MASK 0x00000002
+#define CS35L41_ASP_TX2_EN_SHIFT 1
+#define CS35L41_ASP_TX3_EN_MASK 0x00000004
+#define CS35L41_ASP_TX3_EN_SHIFT 2
+#define CS35L41_ASP_TX4_EN_MASK 0x00000008
+#define CS35L41_ASP_TX4_EN_SHIFT 3
#define CS35L41_ASP_FMT_MASK 0x0700
#define CS35L41_ASP_FMT_SHIFT 8
#define CS35L41_ASP_DOUT_HIZ_MASK 0x03
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index d5bc81099d0d..c2cf3813872a 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -93,47 +93,36 @@ module_param(firmware_autostart, bool, 0444);
MODULE_PARM_DESC(firmware_autostart, "Allow automatic firmware download on boot"
"(0=Disable, 1=Enable) (default=1); ");
+static const char channel_name[3] = { 'L', 'R', 'C' };
+
static const struct reg_sequence cs35l41_hda_config[] = {
{ CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
{ CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN
{ CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz
- { CS35L41_SP_ENABLES, 0x00010000 }, // ASP_RX1_EN = 1
{ CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz
{ CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer
- { CS35L41_SP_HIZ_CTRL, 0x00000002 }, // Hi-Z unused
{ CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot
{ CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1
{ CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC = VMON
{ CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC = IMON
- { CS35L41_ASP_TX3_SRC, 0x00000032 }, // ASPTX3 SRC = ERRVOL
- { CS35L41_ASP_TX4_SRC, 0x00000033 }, // ASPTX4 SRC = CLASSH_TGT
- { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC = ASPRX1
- { CS35L41_DSP1_RX2_SRC, 0x00000009 }, // DSP1RX2 SRC = ASPRX2
{ CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON
{ CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON
+};
+
+static const struct reg_sequence cs35l41_hda_config_no_dsp[] = {
+ { CS35L41_SP_HIZ_CTRL, 0x00000002 }, // Hi-Z unused
+ { CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1
+ { CS35L41_ASP_TX3_SRC, 0x00000000 }, // ASPTX3 SRC = ZERO FILL
+ { CS35L41_ASP_TX4_SRC, 0x00000000 }, // ASPTX4 SRC = ZERO FILL
{ CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC = ERRVOL
+ { CS35L41_DSP1_RX6_SRC, 0x00000021 }, // DSP1RX6 SRC = CLASSH_TGT
};
static const struct reg_sequence cs35l41_hda_config_dsp[] = {
- { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
- { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN
- { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz
- { CS35L41_SP_ENABLES, 0x00010001 }, // ASP_RX1_EN = 1, ASP_TX1_EN = 1
- { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz
- { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer
{ CS35L41_SP_HIZ_CTRL, 0x00000003 }, // Hi-Z unused/disabled
- { CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot
{ CS35L41_DAC_PCM1_SRC, 0x00000032 }, // DACPCM1_SRC = DSP1TX1
- { CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC = VMON
- { CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC = IMON
{ CS35L41_ASP_TX3_SRC, 0x00000028 }, // ASPTX3 SRC = VPMON
{ CS35L41_ASP_TX4_SRC, 0x00000029 }, // ASPTX4 SRC = VBSTMON
- { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC = ASPRX1
- { CS35L41_DSP1_RX2_SRC, 0x00000008 }, // DSP1RX2 SRC = ASPRX1
- { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON
- { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON
{ CS35L41_DSP1_RX6_SRC, 0x00000029 }, // DSP1RX6 SRC = VBSTMON
};
@@ -657,6 +646,41 @@ static void cs35l41_irq_release(struct cs35l41_hda *cs35l41)
cs35l41->irq_errors = 0;
}
+static void cs35l41_update_mixer(struct cs35l41_hda *cs35l41)
+{
+ struct regmap *reg = cs35l41->regmap;
+ unsigned int asp_en = 0;
+ unsigned int dsp1rx2_src = 0;
+
+ regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));
+
+ if (cs35l41->cs_dsp.running) {
+ asp_en |= CS35L41_ASP_TX1_EN_MASK; // ASP_TX1_EN = 1
+ regmap_multi_reg_write(reg, cs35l41_hda_config_dsp,
+ ARRAY_SIZE(cs35l41_hda_config_dsp));
+ if (cs35l41->hw_cfg.bst_type == CS35L41_INT_BOOST)
+ regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VPMON);
+ else
+ regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VBSTMON);
+ } else {
+ regmap_multi_reg_write(reg, cs35l41_hda_config_no_dsp,
+ ARRAY_SIZE(cs35l41_hda_config_no_dsp));
+ }
+
+ if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER) {
+ asp_en |= CS35L41_ASP_RX2_EN_MASK; // ASP_RX2_EN = 1
+ dsp1rx2_src = 0x00000009; // DSP1RX2 SRC = ASPRX2
+ } else {
+ dsp1rx2_src = 0x00000008; // DSP1RX2 SRC = ASPRX1
+ }
+
+ asp_en |= CS35L41_ASP_RX1_EN_MASK; // ASP_RX1_EN = 1
+
+ regmap_write(reg, CS35L41_SP_ENABLES, asp_en);
+ regmap_write(reg, CS35L41_DSP1_RX1_SRC, 0x00000008); // DSP1RX1 SRC = ASPRX1
+ regmap_write(reg, CS35L41_DSP1_RX2_SRC, dsp1rx2_src);
+}
+
static void cs35l41_hda_play_start(struct device *dev)
{
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@@ -671,19 +695,13 @@ static void cs35l41_hda_play_start(struct device *dev)
cs35l41->playback_started = true;
+ cs35l41_update_mixer(cs35l41);
+
if (cs35l41->cs_dsp.running) {
- regmap_multi_reg_write(reg, cs35l41_hda_config_dsp,
- ARRAY_SIZE(cs35l41_hda_config_dsp));
- if (cs35l41->hw_cfg.bst_type == CS35L41_INT_BOOST)
- regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VPMON);
- else
- regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VBSTMON);
regmap_update_bits(reg, CS35L41_PWR_CTRL2,
CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,
1 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT);
cs35l41_set_cspl_mbox_cmd(cs35l41->dev, reg, CSPL_MBOX_CMD_RESUME);
- } else {
- regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));
}
regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
@@ -841,22 +859,31 @@ static void cs35l41_hda_post_playback_hook(struct device *dev, int action)
}
}
-static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot,
- unsigned int rx_num, unsigned int *rx_slot)
+static int cs35l41_hda_channel_map(struct cs35l41_hda *cs35l41)
{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- static const char * const channel_name[] = { "L", "R" };
+ unsigned int tx_num = 0;
+ unsigned int *tx_slot = NULL;
+ unsigned int rx_num;
+ unsigned int *rx_slot;
+ unsigned int mono = 0;
if (!cs35l41->amp_name) {
- if (*rx_slot >= ARRAY_SIZE(channel_name))
+ if (cs35l41->hw_cfg.spk_pos >= ARRAY_SIZE(channel_name))
return -EINVAL;
- cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%s%d",
- channel_name[*rx_slot], cs35l41->channel_index);
+ cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%c%d",
+ channel_name[cs35l41->hw_cfg.spk_pos],
+ cs35l41->channel_index);
if (!cs35l41->amp_name)
return -ENOMEM;
}
+ rx_num = 1;
+ if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER)
+ rx_slot = &mono;
+ else
+ rx_slot = &cs35l41->hw_cfg.spk_pos;
+
return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,
rx_slot);
}
@@ -1495,7 +1522,7 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
"CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",
cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,
cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH,
- cs35l41->hw_cfg.spk_pos ? 'R' : 'L',
+ channel_name[cs35l41->hw_cfg.spk_pos],
cs35l41->cs_dsp.running, cs35l41->speaker_id);
return ret;
@@ -1709,7 +1736,7 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
if (using_irq)
cs35l41_configure_interrupt(cs35l41, irq_pol);
- return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
+ return cs35l41_hda_channel_map(cs35l41);
}
int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id)
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
index c730b3351589..7d003c598e93 100644
--- a/sound/pci/hda/cs35l41_hda.h
+++ b/sound/pci/hda/cs35l41_hda.h
@@ -42,6 +42,7 @@ struct cs35l41_amp_efi_data {
enum cs35l41_hda_spk_pos {
CS35L41_LEFT,
CS35L41_RIGHT,
+ CS35L41_CENTER,
};
enum cs35l41_hda_gpio_function {
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v1 2/2] ALSA: hda/realtek: Add support for ASUS NUC using CS35L41 HDA
2025-06-12 16:00 [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Stefan Binding
2025-06-12 16:00 ` [PATCH v1 1/2] ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA Stefan Binding
@ 2025-06-12 16:00 ` Stefan Binding
2025-06-13 8:20 ` [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Takashi Iwai
2 siblings, 0 replies; 4+ messages in thread
From: Stefan Binding @ 2025-06-12 16:00 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel, patches, Stefan Binding
Add support for ASUS NUC14LNS.
This NUC uses a single CS35L41 Amp in using Internal Boost with SPI.
To support the Single Amp, a new quirk is required.
Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
---
sound/pci/hda/patch_realtek.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bca725bb8281..3d5db33437f2 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7296,6 +7296,11 @@ static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixu
comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 2);
}
+static void cs35l41_fixup_spi_one(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+ comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 1);
+}
+
static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action)
{
comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 4);
@@ -7986,6 +7991,7 @@ enum {
ALC287_FIXUP_CS35L41_I2C_2,
ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED,
ALC287_FIXUP_CS35L41_I2C_4,
+ ALC245_FIXUP_CS35L41_SPI_1,
ALC245_FIXUP_CS35L41_SPI_2,
ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED,
ALC245_FIXUP_CS35L41_SPI_4,
@@ -10112,6 +10118,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l41_fixup_spi_two,
},
+ [ALC245_FIXUP_CS35L41_SPI_1] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cs35l41_fixup_spi_one,
+ },
[ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l41_fixup_spi_two,
@@ -11053,6 +11063,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
+ SND_PCI_QUIRK(0x1043, 0x88f4, "ASUS NUC14LNS", ALC245_FIXUP_CS35L41_SPI_1),
SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41
2025-06-12 16:00 [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Stefan Binding
2025-06-12 16:00 ` [PATCH v1 1/2] ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA Stefan Binding
2025-06-12 16:00 ` [PATCH v1 2/2] ALSA: hda/realtek: Add support for ASUS NUC using " Stefan Binding
@ 2025-06-13 8:20 ` Takashi Iwai
2 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2025-06-13 8:20 UTC (permalink / raw)
To: Stefan Binding
Cc: Jaroslav Kysela, Takashi Iwai, linux-sound, linux-kernel, patches
On Thu, 12 Jun 2025 18:00:21 +0200,
Stefan Binding wrote:
>
> Add support for 1 amp configuration for ASUS NUC using CS35L41.
> The NUC is using 1 CS35L41 amplifier using SPI with Internal Boost.
>
> Stefan Binding (2):
> ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA
> ALSA: hda/realtek: Add support for ASUS NUC using CS35L41 HDA
Applied both patches now to for-next branch.
thanks,
Takashi
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-06-13 8:20 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-12 16:00 [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Stefan Binding
2025-06-12 16:00 ` [PATCH v1 1/2] ALSA: hda: cs35l41: Add support for center channel in CS35L41 HDA Stefan Binding
2025-06-12 16:00 ` [PATCH v1 2/2] ALSA: hda/realtek: Add support for ASUS NUC using " Stefan Binding
2025-06-13 8:20 ` [PATCH v1 0/2] Add Support for ASUS NUC using CS35L41 Takashi Iwai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.