aboutsummaryrefslogtreecommitdiff
path: root/SOURCES/steamdeck-oled-audio.patch
diff options
context:
space:
mode:
Diffstat (limited to 'SOURCES/steamdeck-oled-audio.patch')
-rw-r--r--SOURCES/steamdeck-oled-audio.patch437
1 files changed, 437 insertions, 0 deletions
diff --git a/SOURCES/steamdeck-oled-audio.patch b/SOURCES/steamdeck-oled-audio.patch
new file mode 100644
index 0000000..978e76a
--- /dev/null
+++ b/SOURCES/steamdeck-oled-audio.patch
@@ -0,0 +1,437 @@
+From ba5fcc25b726559cb36d61196c58c865190a8a7b Mon Sep 17 00:00:00 2001
+From c0c65da7ca4b0a4f93272f5e932dd7eed90703c8 Mon Sep 17 00:00:00 2001
+From: Ethan Geller <ethang@valvesoftware.com>
+Date: Thu, 16 Nov 2023 21:31:48 +0000
+Subject: [PATCH] Fix for Max98388 issue where speakers would not be powered on
+ when we resume from S3.
+
+The issue was that when we flush the regmap to the amp on resume, we were also flushing a value of 1 to the SW_RESET pin.
+
+Theoretically, this is fixed by marking the SW_RESET register volatile. However, we did not observe a fix after marking the register volatile, so we opted for a more complete fix of ensuring SW_RESET is zero in our regmap after we have waited for the reset loop to be complete.
+---
+ sound/soc/codecs/max98388.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/codecs/max98388.c b/sound/soc/codecs/max98388.c
+index 293ec172e0a71..4c495e0e33f90 100644
+--- a/sound/soc/codecs/max98388.c
++++ b/sound/soc/codecs/max98388.c
+@@ -391,27 +391,43 @@ void max98388_reset(struct max98388_priv *max98388, struct device *dev)
+ {
+ int ret, reg, count;
+
++
+ /* Software Reset */
+ ret = regmap_update_bits(max98388->regmap,
+ MAX98388_R2000_SW_RESET,
+ MAX98388_SOFT_RESET,
+ MAX98388_SOFT_RESET);
+- if (ret)
++
++ if (ret) {
+ dev_err(dev, "Reset command failed. (ret:%d)\n", ret);
++ goto exit;
++ }
++
+
+ count = 0;
+ while (count < 3) {
+ usleep_range(10000, 11000);
++
+ /* Software Reset Verification */
+ ret = regmap_read(max98388->regmap,
+ MAX98388_R22FF_REV_ID, &reg);
++
+ if (!ret) {
+ dev_info(dev, "Reset completed (retry:%d)\n", count);
+- return;
++ goto exit;
+ }
+ count++;
+ }
++
+ dev_err(dev, "Reset failed. (ret:%d)\n", ret);
++
++
++exit:
++ regcache_cache_only(max98388->regmap, true);
++ ret = regmap_update_bits(max98388->regmap,
++ MAX98388_R2000_SW_RESET,
++ MAX98388_SOFT_RESET, 0);
++ regcache_cache_only(max98388->regmap, false);
+ }
+
+ static int max98388_probe(struct snd_soc_component *component)
+@@ -420,6 +436,7 @@ static int max98388_probe(struct snd_soc_component *component)
+
+ /* Software Reset */
+ max98388_reset(max98388, component->dev);
++ usleep_range(400, 1000);
+
+ /* General channel source configuration */
+ regmap_write(max98388->regmap,
+@@ -812,6 +829,7 @@ static bool max98388_readable_register(struct device *dev,
+ case MAX98388_R210E_AUTO_RESTART:
+ case MAX98388_R210F_GLOBAL_EN:
+ case MAX98388_R22FF_REV_ID:
++ case MAX98388_R2000_SW_RESET:
+ return true;
+ default:
+ return false;
+@@ -824,6 +842,7 @@ static bool max98388_volatile_reg(struct device *dev, unsigned int reg)
+ case MAX98388_R2001_INT_RAW1 ... MAX98388_R2005_INT_STATE2:
+ case MAX98388_R210F_GLOBAL_EN:
+ case MAX98388_R22FF_REV_ID:
++ case MAX98388_R2000_SW_RESET:
+ return true;
+ default:
+ return false;
+@@ -868,6 +887,7 @@ static int max98388_resume(struct device *dev)
+
+ regcache_cache_only(max98388->regmap, false);
+ max98388_reset(max98388, dev);
++ usleep_range(400, 1000);
+ regcache_sync(max98388->regmap);
+
+ return 0;
+--
+GitLab
+
+From 39ecb253ecf7ed12e3019b72d7a226f0525dfaa3 Mon Sep 17 00:00:00 2001
+From: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
+Date: Fri, 20 Oct 2023 15:14:52 +0530
+Subject: [PATCH] ASoC: amd: Add new dmi entries and add condition check for
+ acp config flag
+
+Signed-off-by: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
+(cherry picked from commit 50f20ef9bcf6fdf6e6cc64a031be26fb9cb54849)
+---
+ sound/soc/amd/acp-config.c | 14 ++++++++++++++
+ sound/soc/amd/vangogh/pci-acp5x.c | 3 ++-
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c
+index f27c27580009..73d29a344e70 100644
+--- a/sound/soc/amd/acp-config.c
++++ b/sound/soc/amd/acp-config.c
+@@ -47,6 +47,20 @@ static const struct config_entry config_table[] = {
+ {}
+ },
+ },
++ {
++ .flags = FLAG_AMD_LEGACY,
++ .device = ACP_PCI_DEV_ID,
++ .dmi_table = (const struct dmi_system_id []) {
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Valve"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
++ DMI_MATCH(DMI_PRODUCT_FAMILY, "Aerith"),
++ },
++ },
++ {}
++ },
++ },
+ {
+ .flags = FLAG_AMD_SOF,
+ .device = ACP_PCI_DEV_ID,
+diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c
+index c4634a8a17cd..e29c4cc10e0f 100644
+--- a/sound/soc/amd/vangogh/pci-acp5x.c
++++ b/sound/soc/amd/vangogh/pci-acp5x.c
+@@ -13,6 +13,7 @@
+ #include <linux/pm_runtime.h>
+
+ #include "acp5x.h"
++#include "../mach-config.h"
+
+ struct acp5x_dev_data {
+ void __iomem *acp5x_base;
+@@ -131,7 +132,7 @@ static int snd_acp5x_probe(struct pci_dev *pci,
+
+ /* Return if acp config flag is defined */
+ flag = snd_amd_acp_find_config(pci);
+- if (flag)
++ if (flag != FLAG_AMD_LEGACY)
+ return -ENODEV;
+
+ irqflags = IRQF_SHARED;
+--
+GitLab
+
+From 4855323691ea7dd2288c51cd11f00561f9ba22df Mon Sep 17 00:00:00 2001
+From: Thomas Crider <gloriouseggroll@gmail.com>
+Date: Tue, 5 Dec 2023 05:13:41 -0500
+Subject: [PATCH] cs35l41 fixup
+
+---
+ sound/soc/amd/acp/acp-mach-common.c | 107 ++++++++++++++++++++++++++++
+ sound/soc/amd/acp/acp-mach.h | 4 ++
+ sound/soc/amd/acp/acp-sof-mach.c | 2 +
+ sound/soc/sof/ipc3-topology.c | 11 +--
+ sound/soc/sof/topology.c | 3 +-
+ 5 files changed, 122 insertions(+), 5 deletions(-)
+
+diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
+index a06af82b8..ae32748a5 100644
+--- a/sound/soc/amd/acp/acp-mach-common.c
++++ b/sound/soc/amd/acp/acp-mach-common.c
+@@ -26,6 +26,8 @@
+ #include "../../codecs/rt5682s.h"
+ #include "../../codecs/nau8825.h"
+ #include "../../codecs/nau8821.h"
++#include "../../codecs/cs35l41.h"
++
+ #include "acp-mach.h"
+
+ #define PCO_PLAT_CLK 48000000
+@@ -1243,6 +1245,78 @@ SND_SOC_DAILINK_DEF(nau8821,
+ DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00",
+ "nau8821-hifi")));
+
++static int acp_cs35l41_init(struct snd_soc_pcm_runtime *rtd)
++{
++ return 0;
++}
++
++static int acp_cs35l41_startup(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ runtime->hw.channels_max = DUAL_CHANNEL;
++ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
++ &constraints_channels);
++ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
++ &constraints_rates);
++ return 0;
++}
++
++static int acp_cs35l41_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
++ struct snd_soc_card *card = rtd->card;
++ struct snd_soc_dai *codec_dai;
++ int ret, i;
++ unsigned int num_codecs = rtd->dai_link->num_codecs;
++ unsigned int bclk_val;
++
++ ret = 0;
++ for (i = 0; i < num_codecs; i++) {
++ codec_dai = asoc_rtd_to_codec(rtd, i);
++ if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) {
++ switch (params_rate(params)) {
++ case 48000:
++ bclk_val = 1536000;
++ break;
++ default:
++ dev_err(card->dev, "Invalid Samplerate:0x%x\n",
++ params_rate(params));
++ return -EINVAL;
++ }
++ ret = snd_soc_component_set_sysclk(codec_dai->component,
++ 0, 0, bclk_val, SND_SOC_CLOCK_IN);
++ if (ret < 0) {
++ dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n");
++ return ret;
++ }
++ }
++ }
++
++ return ret;
++}
++
++static struct snd_soc_codec_conf cs35l41_conf[] = {
++ {
++ .dlc = COMP_CODEC_CONF("spi-VLV1776:00"),
++ .name_prefix = "Left",
++ },
++ {
++ .dlc = COMP_CODEC_CONF("spi-VLV1776:01"),
++ .name_prefix = "Right",
++ },
++};
++
++static const struct snd_soc_ops acp_cs35l41_ops = {
++ .startup = acp_cs35l41_startup,
++ .hw_params = acp_cs35l41_hw_params,
++};
++
++SND_SOC_DAILINK_DEF(cs35l41,
++ DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"),
++ COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm")));
++
+ /* Declare DMIC codec components */
+ SND_SOC_DAILINK_DEF(dmic_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
+@@ -1278,6 +1352,8 @@ SND_SOC_DAILINK_DEF(sof_hs,
+ DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
+ SND_SOC_DAILINK_DEF(sof_hs_virtual,
+ DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs-virtual")));
++SND_SOC_DAILINK_DEF(sof_bt,
++ DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-bt")));
+ SND_SOC_DAILINK_DEF(sof_dmic,
+ DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
+ SND_SOC_DAILINK_DEF(pdm_dmic,
+@@ -1336,6 +1412,8 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+
+ if (drv_data->hs_cpu_id)
+ num_links++;
++ if (drv_data->bt_cpu_id)
++ num_links++;
+ if (drv_data->amp_cpu_id)
+ num_links++;
+ if (drv_data->dmic_cpu_id)
+@@ -1421,6 +1499,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+ links[i].platforms = sof_component;
+ links[i].num_platforms = ARRAY_SIZE(sof_component);
+ links[i].dpcm_playback = 1;
++ links[i].dpcm_capture = 1;
+ links[i].nonatomic = true;
+ links[i].no_pcm = 1;
+ if (!drv_data->amp_codec_id) {
+@@ -1453,6 +1532,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+ links[i].platforms = sof_component;
+ links[i].num_platforms = ARRAY_SIZE(sof_component);
+ links[i].dpcm_playback = 1;
++ links[i].dpcm_capture = 1;
+ links[i].nonatomic = true;
+ links[i].no_pcm = 1;
+ if (!drv_data->amp_codec_id) {
+@@ -1482,6 +1562,33 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
+ card->codec_conf = rt1019_conf;
+ card->num_configs = ARRAY_SIZE(rt1019_conf);
+ }
++ if (drv_data->amp_codec_id == CS35L41) {
++ links[i].codecs = cs35l41;
++ links[i].num_codecs = ARRAY_SIZE(cs35l41);
++ links[i].init = acp_cs35l41_init;
++ card->codec_conf = cs35l41_conf;
++ card->num_configs = ARRAY_SIZE(cs35l41_conf);
++ links[i].ops = &acp_cs35l41_ops;
++ }
++ i++;
++ }
++
++ if (drv_data->bt_cpu_id == I2S_BT) {
++ links[i].name = "acp-bt-codec";
++ links[i].id = BT_BE_ID;
++ links[i].cpus = sof_bt;
++ links[i].num_cpus = ARRAY_SIZE(sof_bt);
++ links[i].platforms = sof_component;
++ links[i].num_platforms = ARRAY_SIZE(sof_component);
++ links[i].dpcm_playback = 1;
++ links[i].dpcm_capture = 1;
++ links[i].nonatomic = true;
++ links[i].no_pcm = 1;
++ if (!drv_data->bt_codec_id) {
++ /* Use dummy codec if codec id not specified */
++ links[i].codecs = &asoc_dummy_dlc;
++ links[i].num_codecs = 1;
++ }
+ i++;
+ }
+
+diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
+index 2b3ec6594..6feef5a93 100644
+--- a/sound/soc/amd/acp/acp-mach.h
++++ b/sound/soc/amd/acp/acp-mach.h
+@@ -23,6 +23,7 @@
+ enum be_id {
+ HEADSET_BE_ID = 0,
+ AMP_BE_ID,
++ BT_BE_ID,
+ DMIC_BE_ID,
+ };
+
+@@ -41,6 +42,7 @@ enum codec_endpoints {
+ MAX98360A,
+ RT5682S,
+ NAU8825,
++ CS35L41,
+ NAU8821,
+ MAX98388,
+ };
+@@ -53,9 +55,11 @@ enum platform_end_point {
+ struct acp_card_drvdata {
+ unsigned int hs_cpu_id;
+ unsigned int amp_cpu_id;
++ unsigned int bt_cpu_id;
+ unsigned int dmic_cpu_id;
+ unsigned int hs_codec_id;
+ unsigned int amp_codec_id;
++ unsigned int bt_codec_id;
+ unsigned int dmic_codec_id;
+ unsigned int dai_fmt;
+ unsigned int platform;
+diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
+index 5223033a1..45d4ce17c 100644
+--- a/sound/soc/amd/acp/acp-sof-mach.c
++++ b/sound/soc/amd/acp/acp-sof-mach.c
+@@ -86,9 +86,11 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
+ static struct acp_card_drvdata sof_nau8821_max98388_data = {
+ .hs_cpu_id = I2S_SP,
+ .amp_cpu_id = I2S_HS,
++ .bt_cpu_id = I2S_BT,
+ .dmic_cpu_id = NONE,
+ .hs_codec_id = NAU8821,
+ .amp_codec_id = MAX98388,
++ .bt_codec_id = NONE,
+ .dmic_codec_id = NONE,
+ .soc_mclk = true,
+ .tdm_mode = false,
+diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
+index ba4ef290b..2f070f907 100644
+--- a/sound/soc/sof/ipc3-topology.c
++++ b/sound/soc/sof/ipc3-topology.c
+@@ -1174,6 +1174,7 @@ static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_
+ struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
+ struct sof_dai_private_data *private = dai->private;
+ u32 size = sizeof(*config);
++ int ret;
+
+ /* handle master/slave and inverted clocks */
+ sof_dai_set_format(hw_config, config);
+@@ -1182,12 +1183,14 @@ static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_
+ memset(&config->acpbt, 0, sizeof(config->acpbt));
+ config->hdr.size = size;
+
+- config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
+- config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
++ ret = sof_update_ipc_object(scomp, &config->acpbt, SOF_ACPI2S_TOKENS, slink->tuples,
++ slink->num_tuples, size, slink->num_hw_configs);
++ if (ret < 0)
++ return ret;
+
+- dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n",
++ dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d tdm_mode %d\n",
+ config->dai_index, config->acpbt.tdm_slots,
+- config->acpbt.fsync_rate);
++ config->acpbt.fsync_rate, config->acpbt.tdm_mode);
+
+ dai->number_configs = 1;
+ dai->current_config = 0;
+diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
+index a3a3af252..a634ae05f 100644
+--- a/sound/soc/sof/topology.c
++++ b/sound/soc/sof/topology.c
+@@ -289,7 +289,7 @@ static const struct sof_dai_types sof_dais[] = {
+ {"ALH", SOF_DAI_INTEL_ALH},
+ {"SAI", SOF_DAI_IMX_SAI},
+ {"ESAI", SOF_DAI_IMX_ESAI},
+- {"ACP", SOF_DAI_AMD_BT},
++ {"ACPBT", SOF_DAI_AMD_BT},
+ {"ACPSP", SOF_DAI_AMD_SP},
+ {"ACPDMIC", SOF_DAI_AMD_DMIC},
+ {"ACPHS", SOF_DAI_AMD_HS},
+@@ -1953,6 +1953,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
+ token_id = SOF_ACPDMIC_TOKENS;
+ num_tuples += token_list[SOF_ACPDMIC_TOKENS].count;
+ break;
++ case SOF_DAI_AMD_BT:
+ case SOF_DAI_AMD_SP:
+ case SOF_DAI_AMD_HS:
+ case SOF_DAI_AMD_SP_VIRTUAL:
+--
+2.43.0
+