From a7fc8b862fd5952be791a870ef8ef56016e83ff4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 17 Nov 2023 13:05:56 +0100 Subject: ALSA: hda: Honor subformat when querying PCMs Update mechanism for querying supported PCMs to allow for granular format selection when container size is 32 bits. Currently always the highest bit depth is selected, regardless of how many actual formats codec in question supports. Acked-by: Mark Brown Co-developed-by: Jaroslav Kysela Signed-off-by: Jaroslav Kysela Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20231117120610.1755254-3-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 ++ sound/pci/hda/patch_hdmi.c | 1 + 2 files changed, 3 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 01718b1fc9a7..12f02cdc9659 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3163,6 +3163,7 @@ static int set_pcm_default_values(struct hda_codec *codec, err = snd_hda_query_supported_pcm(codec, info->nid, info->rates ? NULL : &info->rates, info->formats ? NULL : &info->formats, + info->subformats ? NULL : &info->subformats, info->maxbps ? NULL : &info->maxbps); if (err < 0) return err; @@ -3757,6 +3758,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, snd_hda_query_supported_pcm(codec, mout->dig_out_nid, &mout->spdif_rates, &mout->spdif_formats, + NULL, &mout->spdif_maxbps); } mutex_lock(&codec->spdif_mutex); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1cde2a69bdb4..687b8b8fd7ac 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1977,6 +1977,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) err = snd_hda_query_supported_pcm(codec, cvt_nid, &per_cvt->rates, &per_cvt->formats, + NULL, &per_cvt->maxbps); if (err < 0) return err; -- cgit From 61b52df4b64fa1c8860cdfbc548cd0bbe7310082 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 17 Nov 2023 13:05:59 +0100 Subject: ALSA: hda: Switch to new stream-format interface To provide option for selecting different bit-per-sample than just the maximum one, use the new format calculation mechanism. Acked-by: Mark Brown Signed-off-by: Cezary Rojewski Acked-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20231117120610.1755254-6-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_controller.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index c42e9ffff9db..3e7bfeee84fd 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -151,7 +151,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int format_val, stream_tag; + unsigned int format_val, stream_tag, bits; int err; struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); @@ -165,11 +165,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) } snd_hdac_stream_reset(azx_stream(azx_dev)); - format_val = snd_hdac_calc_stream_format(runtime->rate, - runtime->channels, - runtime->format, - hinfo->maxbps, - ctls); + bits = snd_hdac_stream_format_bits(runtime->format, SNDRV_PCM_SUBFORMAT_STD, hinfo->maxbps); + + format_val = snd_hdac_spdif_stream_format(runtime->channels, bits, runtime->rate, ctls); if (!format_val) { dev_err(chip->card->dev, "invalid format_val, rate=%d, ch=%d, format=%d\n", -- cgit From 67ea58daab010ea7a622a89392cc9a6190f8b9c1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 17 Nov 2023 13:06:00 +0100 Subject: ALSA: hda/hdmi: Switch to new stream-format interface To provide option for selecting different bit-per-sample than just the maximum one, use the new format calculation mechanism. Acked-by: Mark Brown Signed-off-by: Cezary Rojewski Acked-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20231117120610.1755254-7-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 687b8b8fd7ac..dff2d7221982 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1655,7 +1655,6 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, #define I915_SILENT_RATE 48000 #define I915_SILENT_CHANNELS 2 -#define I915_SILENT_FORMAT SNDRV_PCM_FORMAT_S16_LE #define I915_SILENT_FORMAT_BITS 16 #define I915_SILENT_FMT_MASK 0xf @@ -1668,8 +1667,8 @@ static void silent_stream_enable_i915(struct hda_codec *codec, per_pin->dev_id, I915_SILENT_RATE); /* trigger silent stream generation in hw */ - format = snd_hdac_calc_stream_format(I915_SILENT_RATE, I915_SILENT_CHANNELS, - I915_SILENT_FORMAT, I915_SILENT_FORMAT_BITS, 0); + format = snd_hdac_stream_format(I915_SILENT_CHANNELS, I915_SILENT_FORMAT_BITS, + I915_SILENT_RATE); snd_hda_codec_setup_stream(codec, per_pin->cvt_nid, I915_SILENT_FMT_MASK, I915_SILENT_FMT_MASK, format); usleep_range(100, 200); -- cgit From 0d41f0c07f19de7fb5790cbe462dddb68af60fa8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 17 Nov 2023 13:06:01 +0100 Subject: ALSA: hda/ca0132: Switch to new stream-format interface To provide option for selecting different bit-per-sample than just the maximum one, use the new format calculation mechanism. Acked-by: Mark Brown Signed-off-by: Cezary Rojewski Acked-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20231117120610.1755254-8-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 748a3c40966e..aa312441604f 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -3022,8 +3022,7 @@ static int dma_convert_to_hda_format(struct hda_codec *codec, { unsigned int format_val; - format_val = snd_hdac_calc_stream_format(sample_rate, - channels, SNDRV_PCM_FORMAT_S32_LE, 32, 0); + format_val = snd_hdac_stream_format(channels, 32, sample_rate); if (hda_format) *hda_format = (unsigned short)format_val; -- cgit From a31014ebad617868c246d3985ff80d891f03711e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 4 Dec 2023 15:27:07 -0600 Subject: ALSA: hda: Intel: add HDA_ARL PCI ID support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yet another PCI ID. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Acked-by: Mark Brown Link: https://lore.kernel.org/r/20231204212710.185976-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index db90feb49c16..d0ade91ab5ac 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2502,6 +2502,8 @@ static const struct pci_device_id azx_ids[] = { { PCI_DEVICE_DATA(INTEL, HDA_LNL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, /* Arrow Lake-S */ { PCI_DEVICE_DATA(INTEL, HDA_ARL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, + /* Arrow Lake */ + { PCI_DEVICE_DATA(INTEL, HDA_ARL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, /* Apollolake (Broxton-P) */ { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, /* Gemini-Lake */ -- cgit From ee694e7db47e1af00ffb29f569904a9ed576868f Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Thu, 21 Dec 2023 13:25:16 +0000 Subject: ALSA: hda: cs35l41: Support additional Dell models without _DSD Add new model entries into configuration table. Signed-off-by: Stefan Binding Cc: # v6.7+ Link: https://lore.kernel.org/r/20231221132518.3213-2-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda_property.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c index 194e1179a253..5eab2de0d4bb 100644 --- a/sound/pci/hda/cs35l41_hda_property.c +++ b/sound/pci/hda/cs35l41_hda_property.c @@ -35,6 +35,10 @@ struct cs35l41_config { }; static const struct cs35l41_config cs35l41_config_table[] = { + { "10280B27", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10280B28", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10280BEB", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, + { "10280C4D", I2C, 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 1, -1, 1000, 4500, 24 }, /* * Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type. * We can override the _DSD to correct the boost type here. @@ -347,6 +351,10 @@ struct cs35l41_prop_model { static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { { "CLSA0100", NULL, lenovo_legion_no_acpi }, { "CLSA0101", NULL, lenovo_legion_no_acpi }, + { "CSC3551", "10280B27", generic_dsd_config }, + { "CSC3551", "10280B28", generic_dsd_config }, + { "CSC3551", "10280BEB", generic_dsd_config }, + { "CSC3551", "10280C4D", generic_dsd_config }, { "CSC3551", "103C89C6", generic_dsd_config }, { "CSC3551", "104312AF", generic_dsd_config }, { "CSC3551", "10431433", generic_dsd_config }, -- cgit From d110858a6925827609d11db8513d76750483ec06 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Thu, 21 Dec 2023 13:25:17 +0000 Subject: ALSA: hda: cs35l41: Prevent firmware load if SPI speed too low Some laptops without _DSD have the SPI speed set very low in the BIOS. Since the SPI controller uses this speed as its max speed, the SPI transactions are very slow. Firmware download writes to many registers, and if the SPI speed is too slow, it can take a long time to download. For this reason, disable firmware loading if the maximum SPI speed is too low. Without Firmware, audio playback will work, but the volume will be low to ensure safe operation of the CS35L41. Signed-off-by: Stefan Binding Cc: # v6.7+ Link: https://lore.kernel.org/r/20231221132518.3213-3-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 25 ++++++++++-- sound/pci/hda/cs35l41_hda.h | 12 +++++- sound/pci/hda/cs35l41_hda_i2c.c | 2 +- sound/pci/hda/cs35l41_hda_property.c | 74 +++++++++++++++++------------------- sound/pci/hda/cs35l41_hda_spi.c | 2 +- 5 files changed, 70 insertions(+), 45 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 92ca2b3b6c92..d3fa6e136744 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" @@ -996,6 +997,11 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) __be32 halo_sts; int ret; + if (cs35l41->bypass_fw) { + dev_warn(cs35l41->dev, "Bypassing Firmware.\n"); + return 0; + } + ret = cs35l41_init_dsp(cs35l41); if (ret) { dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret); @@ -1588,6 +1594,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i u32 values[HDA_MAX_COMPONENTS]; struct acpi_device *adev; struct device *physdev; + struct spi_device *spi; const char *sub; char *property; size_t nval; @@ -1610,7 +1617,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid); if (!ret) { dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n"); - goto put_physdev; + goto out; } property = "cirrus,dev-index"; @@ -1701,8 +1708,20 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i hw_cfg->bst_type = CS35L41_EXT_BOOST; hw_cfg->valid = true; +out: put_device(physdev); + cs35l41->bypass_fw = false; + if (cs35l41->control_bus == SPI) { + spi = to_spi_device(cs35l41->dev); + if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) { + dev_warn(cs35l41->dev, + "SPI speed is too slow to support firmware download: %d Hz.\n", + spi->max_speed_hz); + cs35l41->bypass_fw = true; + } + } + return 0; err: @@ -1711,14 +1730,13 @@ err: hw_cfg->gpio1.valid = false; hw_cfg->gpio2.valid = false; acpi_dev_put(cs35l41->dacpi); -put_physdev: put_device(physdev); return ret; } int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, - struct regmap *regmap) + struct regmap *regmap, enum control_bus control_bus) { unsigned int regid, reg_revid; struct cs35l41_hda *cs35l41; @@ -1737,6 +1755,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i cs35l41->dev = dev; cs35l41->irq = irq; cs35l41->regmap = regmap; + cs35l41->control_bus = control_bus; dev_set_drvdata(dev, cs35l41); ret = cs35l41_hda_read_acpi(cs35l41, device_name, id); diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index 3d925d677213..43d55292b327 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -20,6 +20,8 @@ #include #include +#define CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ 1000000 + struct cs35l41_amp_cal_data { u32 calTarget[2]; u32 calTime[2]; @@ -46,6 +48,11 @@ enum cs35l41_hda_gpio_function { CS35l41_SYNC, }; +enum control_bus { + I2C, + SPI +}; + struct cs35l41_hda { struct device *dev; struct regmap *regmap; @@ -74,6 +81,9 @@ struct cs35l41_hda { struct cs_dsp cs_dsp; struct acpi_device *dacpi; bool mute_override; + enum control_bus control_bus; + bool bypass_fw; + }; enum halo_state { @@ -85,7 +95,7 @@ enum halo_state { extern const struct dev_pm_ops cs35l41_hda_pm_ops; int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, - struct regmap *regmap); + struct regmap *regmap, enum control_bus control_bus); void cs35l41_hda_remove(struct device *dev); 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_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c index b44536fbba17..603e9bff3a71 100644 --- a/sound/pci/hda/cs35l41_hda_i2c.c +++ b/sound/pci/hda/cs35l41_hda_i2c.c @@ -30,7 +30,7 @@ static int cs35l41_hda_i2c_probe(struct i2c_client *clt) return -ENODEV; return cs35l41_hda_probe(&clt->dev, device_name, clt->addr, clt->irq, - devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c)); + devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c), I2C); } static void cs35l41_hda_i2c_remove(struct i2c_client *clt) diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c index 5eab2de0d4bb..be2b01b596c2 100644 --- a/sound/pci/hda/cs35l41_hda_property.c +++ b/sound/pci/hda/cs35l41_hda_property.c @@ -16,10 +16,6 @@ struct cs35l41_config { const char *ssid; - enum { - SPI, - I2C - } bus; int num_amps; enum { INTERNAL, @@ -35,46 +31,46 @@ struct cs35l41_config { }; static const struct cs35l41_config cs35l41_config_table[] = { - { "10280B27", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10280B28", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10280BEB", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, - { "10280C4D", I2C, 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 1, -1, 1000, 4500, 24 }, + { "10280B27", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10280B28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10280BEB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, + { "10280C4D", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 1, -1, 1000, 4500, 24 }, /* * Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type. * We can override the _DSD to correct the boost type here. * Since this laptop has valid ACPI, we do not need to handle cs-gpios, since that already exists * in the ACPI. The Reset GPIO is also valid, so we can use the Reset defined in _DSD. */ - { "103C89C6", SPI, 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 }, - { "104312AF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431433", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431463", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431473", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, - { "10431483", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, - { "10431493", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "104314D3", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "104314E3", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431503", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431533", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431573", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431663", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, - { "104316D3", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, - { "104316F3", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, - { "104317F3", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431863", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "104318D3", I2C, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, - { "10431C9F", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431CAF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431CCF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431CDF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431CEF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, - { "10431D1F", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431DA2", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, - { "10431E02", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, - { "10431EE2", I2C, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, - { "10431F12", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, - { "10431F1F", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, - { "10431F62", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "103C89C6", 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 }, + { "104312AF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431433", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431463", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431473", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, + { "10431483", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, + { "10431493", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "104314D3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "104314E3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431503", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, + { "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431863", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "104318D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "10431C9F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431CAF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431CCF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431CDF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431CEF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, + { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, + { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, {} }; @@ -212,7 +208,7 @@ static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physde "_DSD already exists.\n"); } - if (cfg->bus == SPI) { + if (cs35l41->control_bus == SPI) { cs35l41->index = id; #if IS_ENABLED(CONFIG_SPI) diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c index eb287aa5f782..b76c0dfd5fef 100644 --- a/sound/pci/hda/cs35l41_hda_spi.c +++ b/sound/pci/hda/cs35l41_hda_spi.c @@ -26,7 +26,7 @@ static int cs35l41_hda_spi_probe(struct spi_device *spi) return -ENODEV; return cs35l41_hda_probe(&spi->dev, device_name, spi_get_chipselect(spi, 0), spi->irq, - devm_regmap_init_spi(spi, &cs35l41_regmap_spi)); + devm_regmap_init_spi(spi, &cs35l41_regmap_spi), SPI); } static void cs35l41_hda_spi_remove(struct spi_device *spi) -- cgit From 423206604b28174698d77bf5ea81365cdd6c0f77 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Thu, 21 Dec 2023 13:25:18 +0000 Subject: ALSA: hda/realtek: Add quirks for Dell models These models use 2 or 4 CS35L41 amps with HDA using SPI and I2C. Models use internal and external boost. All models require DSD support to be added inside cs35l41_hda_property.c Signed-off-by: Stefan Binding Cc: # v6.7+ Link: https://lore.kernel.org/r/20231221132518.3213-4-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c3a756528886..19040887ff67 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6956,6 +6956,11 @@ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2); } +static void cs35l41_fixup_i2c_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action) +{ + cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 4); +} + static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action) { cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 2); @@ -7441,6 +7446,7 @@ enum { ALC287_FIXUP_LEGION_16ACHG6, ALC287_FIXUP_CS35L41_I2C_2, ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED, + ALC287_FIXUP_CS35L41_I2C_4, ALC245_FIXUP_CS35L41_SPI_2, ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED, ALC245_FIXUP_CS35L41_SPI_4, @@ -9427,6 +9433,10 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_HP_MUTE_LED, }, + [ALC287_FIXUP_CS35L41_I2C_4] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs35l41_fixup_i2c_four, + }, [ALC245_FIXUP_CS35L41_SPI_2] = { .type = HDA_FIXUP_FUNC, .v.func = cs35l41_fixup_spi_two, @@ -9703,6 +9713,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x0b27, "Dell", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1028, 0x0b28, "Dell", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2), @@ -9713,6 +9725,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS), SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS), SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS), + SND_PCI_QUIRK(0x1028, 0x0c4d, "Dell", ALC287_FIXUP_CS35L41_I2C_4), SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2), SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2), SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC289_FIXUP_DELL_CS35L41_SPI_2), -- cgit From 68f7f3ff6c2a0998be9dc07622bd0d16fd1fda20 Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Sat, 30 Dec 2023 01:13:41 +0100 Subject: ALSA: hda/tas2781: configure the amp after firmware load Make the amp available immediately after a module load to avoid having to wait for a PCM hook action. (eg. unloading & loading the module while listening music) Signed-off-by: Gergo Koteles Link: https://lore.kernel.org/r/7f2f65d9212aa16edd4db8725489ae59dbe74c66.1703895108.git.soyer@irl.hu Signed-off-by: Takashi Iwai --- sound/pci/hda/tas2781_hda_i2c.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index dfe281b57aa6..c8523df4105f 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -584,6 +584,8 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) */ tas2781_save_calibration(tas_priv); + tasdevice_tuning_switch(tas_hda->priv, 0); + out: mutex_unlock(&tas_hda->priv->codec_lock); if (fmw) -- cgit From 99af5b11c57d33c32d761797f6308b40936c22ed Mon Sep 17 00:00:00 2001 From: Dorian Cruveiller Date: Sat, 30 Dec 2023 12:40:01 +0100 Subject: ALSA: hda/realtek: enable SND_PCI_QUIRK for Lenovo Legion Slim 7 Gen 8 (2023) serie Link up the realtek audio chip to the cirrus cs35l41 sound amplifier chip on 4 models of the Lenovo legion slim 7 gen 8 (2023). These models are 16IRH8 (2 differents subsystem id) and 16APH8 (2 differents subsystem ids). Subsystem ids list: - 17AA38B4 - 17AA38B5 - 17AA38B6 - 17AA38B7 Signed-off-by: Dorian Cruveiller Cc: # v6.7 Link: https://lore.kernel.org/r/20231230114001.19855-1-doriancruveiller@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 19040887ff67..bc4e3a85137c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10239,6 +10239,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C), + SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x38b7, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C), -- cgit From ba7053b4b4a4ddcf530fa2b897e697004715d086 Mon Sep 17 00:00:00 2001 From: Dorian Cruveiller Date: Sat, 30 Dec 2023 12:43:12 +0100 Subject: ALSA: hda: Add driver properties for cs35l41 for Lenovo Legion Slim 7 Gen 8 serie Add driver properties on 4 models of this laptop serie since they don't have _DSD in the ACPI table Signed-off-by: Dorian Cruveiller Cc: # v6.7 Link: https://lore.kernel.org/r/20231230114312.22118-1-doriancruveiller@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda_property.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c index be2b01b596c2..52820ca9c603 100644 --- a/sound/pci/hda/cs35l41_hda_property.c +++ b/sound/pci/hda/cs35l41_hda_property.c @@ -71,6 +71,10 @@ static const struct cs35l41_config cs35l41_config_table[] = { { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, {} }; @@ -381,6 +385,10 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { { "CSC3551", "10431F12", generic_dsd_config }, { "CSC3551", "10431F1F", generic_dsd_config }, { "CSC3551", "10431F62", generic_dsd_config }, + { "CSC3551", "17AA38B4", generic_dsd_config }, + { "CSC3551", "17AA38B5", generic_dsd_config }, + { "CSC3551", "17AA38B6", generic_dsd_config }, + { "CSC3551", "17AA38B7", generic_dsd_config }, {} }; -- cgit From 76f5f55c45b906710c9565a7e68c8d782c46b394 Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Sat, 30 Dec 2023 01:09:42 +0100 Subject: ALSA: hda/tas2781: add ptrs to calibration functions Make calibration functions configurable to support different calibration data storage modes. Signed-off-by: Gergo Koteles Link: https://lore.kernel.org/r/5859c77ffef752b8a9784713b412d815d7e2688c.1703891777.git.soyer@irl.hu Signed-off-by: Takashi Iwai --- sound/pci/hda/tas2781_hda_i2c.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index c8523df4105f..4b639120c981 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -479,7 +479,7 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - tas2781_apply_calib(tas_priv); + tasdevice_apply_calibration(tas_priv); } else tas_priv->cali_data.total_sz = 0; @@ -582,7 +582,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) /* If calibrated data occurs error, dsp will still works with default * calibrated data inside algo. */ - tas2781_save_calibration(tas_priv); + tasdevice_save_calibration(tas_priv); tasdevice_tuning_switch(tas_hda->priv, 0); @@ -685,10 +685,6 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) const char *device_name; int ret; - if (strstr(dev_name(&clt->dev), "TIAS2781")) - device_name = "TIAS2781"; - else - return -ENODEV; tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL); if (!tas_hda) @@ -701,6 +697,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) if (!tas_hda->priv) return -ENOMEM; + if (strstr(dev_name(&clt->dev), "TIAS2781")) { + device_name = "TIAS2781"; + tas_hda->priv->save_calibration = tas2781_save_calibration; + tas_hda->priv->apply_calibration = tas2781_apply_calib; + } else + return -ENODEV; + tas_hda->priv->irq_info.irq = clt->irq; ret = tas2781_read_acpi(tas_hda->priv, device_name); if (ret) @@ -767,8 +770,6 @@ static int tas2781_runtime_suspend(struct device *dev) static int tas2781_runtime_resume(struct device *dev) { struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - unsigned long calib_data_sz = - tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE; dev_dbg(tas_hda->dev, "Runtime Resume\n"); @@ -779,8 +780,7 @@ static int tas2781_runtime_resume(struct device *dev) /* If calibrated data occurs error, dsp will still works with default * calibrated data inside algo. */ - if (tas_hda->priv->cali_data.total_sz > calib_data_sz) - tas2781_apply_calib(tas_hda->priv); + tasdevice_apply_calibration(tas_hda->priv); mutex_unlock(&tas_hda->priv->codec_lock); @@ -811,8 +811,6 @@ static int tas2781_system_suspend(struct device *dev) static int tas2781_system_resume(struct device *dev) { struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - unsigned long calib_data_sz = - tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE; int i, ret; dev_info(tas_hda->priv->dev, "System Resume\n"); @@ -834,8 +832,7 @@ static int tas2781_system_resume(struct device *dev) /* If calibrated data occurs error, dsp will still work with default * calibrated data inside algo. */ - if (tas_hda->priv->cali_data.total_sz > calib_data_sz) - tas2781_apply_calib(tas_hda->priv); + tasdevice_apply_calibration(tas_hda->priv); mutex_unlock(&tas_hda->priv->codec_lock); return 0; -- cgit From c021ca729fe870d25a4798491c383c89b3091650 Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Sat, 30 Dec 2023 01:09:43 +0100 Subject: ALSA: hda/tas2781: add configurable global i2c address Make the global i2c address configurable to support compatible amplifiers with different global i2c address. Signed-off-by: Gergo Koteles Link: https://lore.kernel.org/r/a252f1efeed5049f027f01e699c9e10e1e05bf9e.1703891777.git.soyer@irl.hu Signed-off-by: Takashi Iwai --- sound/pci/hda/tas2781_hda_i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 4b639120c981..503be3fbce56 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -81,7 +81,7 @@ static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) if (i2c_acpi_get_i2c_resource(ares, &sb)) { if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS && - sb->slave_address != TAS2781_GLOBAL_ADDR) { + sb->slave_address != tas_priv->global_addr) { tas_priv->tasdevice[tas_priv->ndev].dev_addr = (unsigned int)sb->slave_address; tas_priv->ndev++; @@ -701,6 +701,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) device_name = "TIAS2781"; tas_hda->priv->save_calibration = tas2781_save_calibration; tas_hda->priv->apply_calibration = tas2781_apply_calib; + tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; } else return -ENODEV; -- cgit From c3ca4458cc2f719b1652abaa8d2fbf7f3d4311cb Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Sat, 30 Dec 2023 01:09:44 +0100 Subject: ALSA: hda/tas2781: add TAS2563 support for 14ARB7 The INT8866 belongs to the Lenovo Yoga 7 Gen 7 AMD 14ARB7 laptop. It has two TAS2563 amplifier. Add the PNP ID and calibration functions to handle them. ACPI excerpt: Scope (_SB.I2CD) { Device (TAS) { Name (_HID, "INT8866") // _HID: Hardware ID Name (_UID, Zero) // _UID: Unique ID Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { Name (RBUF, ResourceTemplate () { I2cSerialBusV2 (0x004C, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.I2CD", 0x00, ResourceConsumer, , Exclusive, ) I2cSerialBusV2 (0x004D, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.I2CD", 0x00, ResourceConsumer, , Exclusive, ) GpioInt (Edge, ActiveLow, SharedAndWake, PullNone, 0x0000, "\\_SB.GPIO", 0x00, ResourceConsumer, , ) { // Pin list 0x0020 } }) Return (RBUF) /* \_SB_.I2CD.TAS_._CRS.RBUF */ } Method (_STA, 0, NotSerialized) // _STA: Status { Return (0x0F) } } } Signed-off-by: Gergo Koteles Link: https://lore.kernel.org/r/3b8d4c602e1a46922f53bc9afc8b705d55aa4872.1703891777.git.soyer@irl.hu Signed-off-by: Takashi Iwai --- sound/pci/hda/tas2781_hda_i2c.c | 87 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 503be3fbce56..4805cf0b6480 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -65,6 +65,24 @@ enum calib_data { CALIB_MAX }; +#define TAS2563_MAX_CHANNELS 4 + +#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) +#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) +#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) +#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) +#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) +#define TAS2563_CAL_N 5 +#define TAS2563_CAL_DATA_SIZE 4 +#define TAS2563_CAL_CH_SIZE 20 +#define TAS2563_CAL_ARRAY_SIZE 80 + +static unsigned int cal_regs[TAS2563_CAL_N] = { + TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0, + TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM, +}; + + struct tas2781_hda { struct device *dev; struct tasdevice_priv *priv; @@ -404,6 +422,69 @@ static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = { .put = tasdevice_config_put, }; +static void tas2563_apply_calib(struct tasdevice_priv *tas_priv) +{ + unsigned int data; + int offset = 0; + int ret; + + for (int i = 0; i < tas_priv->ndev; i++) { + for (int j = 0; j < TAS2563_CAL_N; ++j) { + data = cpu_to_be32( + *(uint32_t *)&tas_priv->cali_data.data[offset]); + ret = tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j], + (unsigned char *)&data, TAS2563_CAL_DATA_SIZE); + if (ret) + dev_err(tas_priv->dev, + "Error writing calib regs\n"); + offset += TAS2563_CAL_DATA_SIZE; + } + } +} + +static int tas2563_save_calibration(struct tasdevice_priv *tas_priv) +{ + static efi_guid_t efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, + 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); + + static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TAS2563_CAL_N] = { + { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" }, + { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" }, + { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" }, + { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" }, + }; + + unsigned long max_size = TAS2563_CAL_DATA_SIZE; + unsigned int offset = 0; + efi_status_t status; + unsigned int attr; + + tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, + TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL); + if (!tas_priv->cali_data.data) + return -ENOMEM; + + for (int i = 0; i < tas_priv->ndev; ++i) { + for (int j = 0; j < TAS2563_CAL_N; ++j) { + status = efi.get_variable(efi_vars[i][j], + &efi_guid, &attr, &max_size, + &tas_priv->cali_data.data[offset]); + if (status != EFI_SUCCESS || + max_size != TAS2563_CAL_DATA_SIZE) { + dev_warn(tas_priv->dev, + "Calibration data read failed %ld\n", status); + return -EINVAL; + } + offset += TAS2563_CAL_DATA_SIZE; + } + } + + tas_priv->cali_data.total_sz = offset; + tasdevice_apply_calibration(tas_priv); + + return 0; +} + static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) { static const unsigned char page_array[CALIB_MAX] = { @@ -702,6 +783,11 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) tas_hda->priv->save_calibration = tas2781_save_calibration; tas_hda->priv->apply_calibration = tas2781_apply_calib; tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; + } else if (strstr(dev_name(&clt->dev), "INT8866")) { + device_name = "INT8866"; + tas_hda->priv->save_calibration = tas2563_save_calibration; + tas_hda->priv->apply_calibration = tas2563_apply_calib; + tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; } else return -ENODEV; @@ -851,6 +937,7 @@ static const struct i2c_device_id tas2781_hda_i2c_id[] = { static const struct acpi_device_id tas2781_acpi_hda_match[] = { {"TIAS2781", 0 }, + {"INT8866", 0 }, {} }; MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); -- cgit From b5cb53fd32779f3a971c45bcd997ae2608aa1086 Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Sat, 30 Dec 2023 01:09:45 +0100 Subject: ALSA: hda/tas2781: add fixup for Lenovo 14ARB7 The 14ARB7 has two tas2563 amplifier on i2c. Connect it to the tas2781 driver. Signed-off-by: Gergo Koteles Link: https://lore.kernel.org/r/abce9ee55689523562feb72383377171a489ddc7.1703891777.git.soyer@irl.hu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bc4e3a85137c..664729989a7f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6989,6 +6989,12 @@ static void tas2781_fixup_i2c(struct hda_codec *cdc, tas2781_generic_fixup(cdc, action, "i2c", "TIAS2781"); } +static void yoga7_14arb7_fixup_i2c(struct hda_codec *cdc, + const struct hda_fixup *fix, int action) +{ + tas2781_generic_fixup(cdc, action, "i2c", "INT8866"); +} + /* for alc295_fixup_hp_top_speakers */ #include "hp_x360_helper.c" @@ -7460,6 +7466,7 @@ enum { ALC236_FIXUP_DELL_DUAL_CODECS, ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI, ALC287_FIXUP_TAS2781_I2C, + ALC287_FIXUP_YOGA7_14ARB7_I2C, ALC245_FIXUP_HP_MUTE_LED_COEFBIT, ALC245_FIXUP_HP_X360_MUTE_LEDS, ALC287_FIXUP_THINKPAD_I2S_SPK, @@ -9578,6 +9585,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_THINKPAD_ACPI, }, + [ALC287_FIXUP_YOGA7_14ARB7_I2C] = { + .type = HDA_FIXUP_FUNC, + .v.func = yoga7_14arb7_fixup_i2c, + .chained = true, + .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK, + }, [ALC245_FIXUP_HP_MUTE_LED_COEFBIT] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_mute_led_coefbit, @@ -10231,6 +10244,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), + SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C), -- cgit From 7d65d70161ef75a3991480c91668ac11acedf211 Mon Sep 17 00:00:00 2001 From: Lorenz Brun Date: Tue, 2 Jan 2024 22:48:20 +0100 Subject: ALSA: hda: cs35l41: Support more HP models without _DSD This adds overrides for a series of notebooks using a common config taken from HP's proprietary Windows driver. This has been tested on a HP 15-ey0xxxx device (subsystem 103C8A31) together with another Realtek quirk and the calibration files from the proprietary driver. Signed-off-by: Lorenz Brun Cc: # v6.7 Link: https://lore.kernel.org/r/20240102214821.3394810-1-lorenz@brun.one Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda_property.c | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'sound/pci/hda') diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c index 52820ca9c603..fcc605be51cf 100644 --- a/sound/pci/hda/cs35l41_hda_property.c +++ b/sound/pci/hda/cs35l41_hda_property.c @@ -42,6 +42,28 @@ static const struct cs35l41_config cs35l41_config_table[] = { * in the ACPI. The Reset GPIO is also valid, so we can use the Reset defined in _DSD. */ { "103C89C6", 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 }, + { "103C8A28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A29", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A2A", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A2B", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A2C", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A2D", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A2E", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A30", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8A31", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BB3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BB4", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BDF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE0", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE1", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE2", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE9", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BDD", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BDE", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE5", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8BE6", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, + { "103C8B3A", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 }, { "104312AF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, { "10431433", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, { "10431463", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, @@ -356,6 +378,28 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { { "CSC3551", "10280BEB", generic_dsd_config }, { "CSC3551", "10280C4D", generic_dsd_config }, { "CSC3551", "103C89C6", generic_dsd_config }, + { "CSC3551", "103C8A28", generic_dsd_config }, + { "CSC3551", "103C8A29", generic_dsd_config }, + { "CSC3551", "103C8A2A", generic_dsd_config }, + { "CSC3551", "103C8A2B", generic_dsd_config }, + { "CSC3551", "103C8A2C", generic_dsd_config }, + { "CSC3551", "103C8A2D", generic_dsd_config }, + { "CSC3551", "103C8A2E", generic_dsd_config }, + { "CSC3551", "103C8A30", generic_dsd_config }, + { "CSC3551", "103C8A31", generic_dsd_config }, + { "CSC3551", "103C8BB3", generic_dsd_config }, + { "CSC3551", "103C8BB4", generic_dsd_config }, + { "CSC3551", "103C8BDF", generic_dsd_config }, + { "CSC3551", "103C8BE0", generic_dsd_config }, + { "CSC3551", "103C8BE1", generic_dsd_config }, + { "CSC3551", "103C8BE2", generic_dsd_config }, + { "CSC3551", "103C8BE9", generic_dsd_config }, + { "CSC3551", "103C8BDD", generic_dsd_config }, + { "CSC3551", "103C8BDE", generic_dsd_config }, + { "CSC3551", "103C8BE3", generic_dsd_config }, + { "CSC3551", "103C8BE5", generic_dsd_config }, + { "CSC3551", "103C8BE6", generic_dsd_config }, + { "CSC3551", "103C8B3A", generic_dsd_config }, { "CSC3551", "104312AF", generic_dsd_config }, { "CSC3551", "10431433", generic_dsd_config }, { "CSC3551", "10431463", generic_dsd_config }, -- cgit