Merge branch 'for-linus' into for-next
authorTakashi Iwai <tiwai@suse.de>
Thu, 24 Aug 2023 07:27:21 +0000 (09:27 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 24 Aug 2023 07:27:21 +0000 (09:27 +0200)
Back-merge the 6.5-devel branch for the clean patch application for
6.6 and resolving merge conflicts.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
1  2 
sound/pci/hda/patch_realtek.c
sound/soc/codecs/cs35l41.c
sound/soc/codecs/cs35l56-i2c.c
sound/soc/codecs/cs35l56-spi.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/es8316.c
sound/soc/codecs/rt722-sdca-sdw.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/fsl_spdif.c
sound/soc/soc-pcm.c

index e294f3b0c9d1a47225246ac4441536c4a6346ed5,dc7b7a407638a76c959e9a3470fbf2af4b888630..54e17791c6a8a369457e4436146551230e331df8
@@@ -6716,20 -6716,12 +6716,20 @@@ static void comp_generic_playback_hook(
        int i;
  
        for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
 -              if (spec->comps[i].dev)
 +              if (spec->comps[i].dev && spec->comps[i].pre_playback_hook)
 +                      spec->comps[i].pre_playback_hook(spec->comps[i].dev, action);
 +      }
 +      for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
 +              if (spec->comps[i].dev && spec->comps[i].playback_hook)
                        spec->comps[i].playback_hook(spec->comps[i].dev, action);
        }
 +      for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
 +              if (spec->comps[i].dev && spec->comps[i].post_playback_hook)
 +                      spec->comps[i].post_playback_hook(spec->comps[i].dev, action);
 +      }
  }
  
 -struct cs35l41_dev_name {
 +struct scodec_dev_name {
        const char *bus;
        const char *hid;
        int index;
  /* match the device name in a slightly relaxed manner */
  static int comp_match_cs35l41_dev_name(struct device *dev, void *data)
  {
 -      struct cs35l41_dev_name *p = data;
 +      struct scodec_dev_name *p = data;
        const char *d = dev_name(dev);
        int n = strlen(p->bus);
        char tmp[32];
        return !strcmp(d + n, tmp);
  }
  
 +static int comp_match_tas2781_dev_name(struct device *dev,
 +      void *data)
 +{
 +      struct scodec_dev_name *p = data;
 +      const char *d = dev_name(dev);
 +      int n = strlen(p->bus);
 +      char tmp[32];
 +
 +      /* check the bus name */
 +      if (strncmp(d, p->bus, n))
 +              return 0;
 +      /* skip the bus number */
 +      if (isdigit(d[n]))
 +              n++;
 +      /* the rest must be exact matching */
 +      snprintf(tmp, sizeof(tmp), "-%s:00", p->hid);
 +
 +      return !strcmp(d + n, tmp);
 +}
 +
  static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
                                  const char *hid, int count)
  {
        struct device *dev = hda_codec_dev(cdc);
        struct alc_spec *spec = cdc->spec;
 -      struct cs35l41_dev_name *rec;
 +      struct scodec_dev_name *rec;
        int ret, i;
  
        switch (action) {
        }
  }
  
 +static void tas2781_generic_fixup(struct hda_codec *cdc, int action,
 +      const char *bus, const char *hid)
 +{
 +      struct device *dev = hda_codec_dev(cdc);
 +      struct alc_spec *spec = cdc->spec;
 +      struct scodec_dev_name *rec;
 +      int ret;
 +
 +      switch (action) {
 +      case HDA_FIXUP_ACT_PRE_PROBE:
 +              rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL);
 +              if (!rec)
 +                      return;
 +              rec->bus = bus;
 +              rec->hid = hid;
 +              rec->index = 0;
 +              spec->comps[0].codec = cdc;
 +              component_match_add(dev, &spec->match,
 +                      comp_match_tas2781_dev_name, rec);
 +              ret = component_master_add_with_match(dev, &comp_master_ops,
 +                      spec->match);
 +              if (ret)
 +                      codec_err(cdc,
 +                              "Fail to register component aggregator %d\n",
 +                              ret);
 +              else
 +                      spec->gen.pcm_playback_hook =
 +                              comp_generic_playback_hook;
 +              break;
 +      case HDA_FIXUP_ACT_FREE:
 +              component_master_del(dev, &comp_master_ops);
 +              break;
 +      }
 +}
 +
  static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
  {
        cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2);
@@@ -6869,12 -6806,6 +6869,12 @@@ static void alc287_fixup_legion_16ithg6
        cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0101", 2);
  }
  
 +static void tas2781_fixup_i2c(struct hda_codec *cdc,
 +      const struct hda_fixup *fix, int action)
 +{
 +       tas2781_generic_fixup(cdc, action, "i2c", "TIAS2781");
 +}
 +
  /* for alc295_fixup_hp_top_speakers */
  #include "hp_x360_helper.c"
  
@@@ -7300,7 -7231,6 +7300,7 @@@ enum 
        ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
        ALC236_FIXUP_DELL_DUAL_CODECS,
        ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
 +      ALC287_FIXUP_TAS2781_I2C,
  };
  
  /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@@ -9379,12 -9309,6 +9379,12 @@@ static const struct hda_fixup alc269_fi
                .chained = true,
                .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
        },
 +      [ALC287_FIXUP_TAS2781_I2C] = {
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = tas2781_fixup_i2c,
 +              .chained = true,
 +              .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
 +      },
  };
  
  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC245_FIXUP_CS35L41_SPI_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis MLK 14 RPL-P", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
        SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+       SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
-       SND_PCI_QUIRK(0x103c, 0x8c26, "HP HP EliteBook 800G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c47, "HP EliteBook 840 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c48, "HP EliteBook 860 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c49, "HP Elite x360 830 2-in-1 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),
        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, 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),
 +      SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
 +      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, 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),
 +      SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C),
 +      SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C),
 +      SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
 +      SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@@ -10726,6 -10643,7 +10733,7 @@@ static int patch_alc269(struct hda_code
        spec = codec->spec;
        spec->gen.shared_mic_vref_pin = 0x18;
        codec->power_save_node = 0;
+       spec->en_3kpull_low = true;
  
  #ifdef CONFIG_PM
        codec->patch_ops.suspend = alc269_suspend;
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
-               if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD)
-                       spec->en_3kpull_low = true;
+               if (codec->core.vendor_id == 0x10ec0236 &&
+                   codec->bus->pci->vendor != PCI_VENDOR_ID_AMD)
+                       spec->en_3kpull_low = false;
                break;
        case 0x10ec0257:
                spec->codec_variant = ALC269_TYPE_ALC257;
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0;
+               spec->en_3kpull_low = false;
                break;
        case 0x10ec0215:
        case 0x10ec0245:
index 2b3c36f02edb07b11b250c6151be93a0b2281122,8a879b6f48290949d73baa5ff6b89f1218b6deba..722b69a6de26ca29d726a19b24ff21e2e2c57bed
@@@ -168,7 -168,7 +168,7 @@@ static int cs35l41_get_fs_mon_config_in
  static const DECLARE_TLV_DB_RANGE(dig_vol_tlv,
                0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
                1, 913, TLV_DB_MINMAX_ITEM(-10200, 1200));
- static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
+ static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 50, 100, 0);
  
  static const struct snd_kcontrol_new dre_ctrl =
        SOC_DAPM_SINGLE("Switch", CS35L41_PWR_CTRL3, 20, 1, 0);
@@@ -491,6 -491,7 +491,6 @@@ static int cs35l41_main_amp_event(struc
  {
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
        struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
 -      unsigned int val;
        int ret = 0;
  
        switch (event) {
                                                cs35l41_pup_patch,
                                                ARRAY_SIZE(cs35l41_pup_patch));
  
 -              cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1,
 -                                    &cs35l41->pll_lock);
 +              ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type,
 +                                          1, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running);
                break;
        case SND_SOC_DAPM_POST_PMD:
 -              cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0,
 -                                    &cs35l41->pll_lock);
 -
 -              ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
 -                                             val, val &  CS35L41_PDN_DONE_MASK,
 -                                             1000, 100000);
 -              if (ret)
 -                      dev_warn(cs35l41->dev, "PDN failed: %d\n", ret);
 -
 -              regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
 -                           CS35L41_PDN_DONE_MASK);
 +              ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type,
 +                                          0, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running);
  
                regmap_multi_reg_write_bypassed(cs35l41->regmap,
                                                cs35l41_pdn_patch,
index 888fdfa5f5dbe8dc6f8deff966c4f0618813fff1,40666e6698ba99d58d5f4be3992751178cbcefc1..9f4f2f4f23f5668c846f2a051eee64c533deb38f
@@@ -26,14 -26,14 +26,14 @@@ static int cs35l56_i2c_probe(struct i2c
        if (!cs35l56)
                return -ENOMEM;
  
 -      cs35l56->dev = dev;
 -      cs35l56->can_hibernate = true;
 +      cs35l56->base.dev = dev;
 +      cs35l56->base.can_hibernate = true;
  
        i2c_set_clientdata(client, cs35l56);
 -      cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config);
 -      if (IS_ERR(cs35l56->regmap)) {
 -              ret = PTR_ERR(cs35l56->regmap);
 -              return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n");
 +      cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config);
 +      if (IS_ERR(cs35l56->base.regmap)) {
 +              ret = PTR_ERR(cs35l56->base.regmap);
 +              return dev_err_probe(cs35l56->base.dev, ret, "Failed to allocate register map\n");
        }
  
        ret = cs35l56_common_probe(cs35l56);
@@@ -42,7 -42,7 +42,7 @@@
  
        ret = cs35l56_init(cs35l56);
        if (ret == 0)
 -              ret = cs35l56_irq_request(cs35l56, client->irq);
 +              ret = cs35l56_irq_request(&cs35l56->base, client->irq);
        if (ret < 0)
                cs35l56_remove(cs35l56);
  
@@@ -62,10 -62,19 +62,19 @@@ static const struct i2c_device_id cs35l
  };
  MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c);
  
+ #ifdef CONFIG_ACPI
+ static const struct acpi_device_id cs35l56_asoc_acpi_match[] = {
+       { "CSC355C", 0 },
+       {},
+ };
+ MODULE_DEVICE_TABLE(acpi, cs35l56_asoc_acpi_match);
+ #endif
  static struct i2c_driver cs35l56_i2c_driver = {
        .driver = {
                .name           = "cs35l56",
                .pm = &cs35l56_pm_ops_i2c_spi,
+               .acpi_match_table = ACPI_PTR(cs35l56_asoc_acpi_match),
        },
        .id_table       = cs35l56_id_i2c,
        .probe          = cs35l56_i2c_probe,
index 2057fce435be6ba43675a15a7bd852b852f4223b,302f9c47407a404b756cf9a394b26c32eab95278..9962703915e1f146d682af2b05a2175014dcee9a
@@@ -25,13 -25,13 +25,13 @@@ static int cs35l56_spi_probe(struct spi
                return -ENOMEM;
  
        spi_set_drvdata(spi, cs35l56);
 -      cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config);
 -      if (IS_ERR(cs35l56->regmap)) {
 -              ret = PTR_ERR(cs35l56->regmap);
 +      cs35l56->base.regmap = devm_regmap_init_spi(spi, regmap_config);
 +      if (IS_ERR(cs35l56->base.regmap)) {
 +              ret = PTR_ERR(cs35l56->base.regmap);
                return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n");
        }
  
 -      cs35l56->dev = &spi->dev;
 +      cs35l56->base.dev = &spi->dev;
  
        ret = cs35l56_common_probe(cs35l56);
        if (ret != 0)
@@@ -39,7 -39,7 +39,7 @@@
  
        ret = cs35l56_init(cs35l56);
        if (ret == 0)
 -              ret = cs35l56_irq_request(cs35l56, spi->irq);
 +              ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
        if (ret < 0)
                cs35l56_remove(cs35l56);
  
@@@ -59,10 -59,19 +59,19 @@@ static const struct spi_device_id cs35l
  };
  MODULE_DEVICE_TABLE(spi, cs35l56_id_spi);
  
+ #ifdef CONFIG_ACPI
+ static const struct acpi_device_id cs35l56_asoc_acpi_match[] = {
+       { "CSC355C", 0 },
+       {},
+ };
+ MODULE_DEVICE_TABLE(acpi, cs35l56_asoc_acpi_match);
+ #endif
  static struct spi_driver cs35l56_spi_driver = {
        .driver = {
                .name           = "cs35l56",
                .pm = &cs35l56_pm_ops_i2c_spi,
+               .acpi_match_table = ACPI_PTR(cs35l56_asoc_acpi_match),
        },
        .id_table       = cs35l56_id_spi,
        .probe          = cs35l56_spi_probe,
index 19b6b4fbe5de8d48af361da7c5c1117bd93acebb,fd06b9f9d496d6727cdfadc24ad659185cc9b98e..ea3a4557619a743cde50389f8cdb4026356b6ca2
@@@ -5,7 -5,6 +5,6 @@@
  // Copyright (C) 2023 Cirrus Logic, Inc. and
  //                    Cirrus Logic International Semiconductor Ltd.
  
- #include <linux/acpi.h>
  #include <linux/completion.h>
  #include <linux/debugfs.h>
  #include <linux/delay.h>
  static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w,
                             struct snd_kcontrol *kcontrol, int event);
  
 -static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command)
 -{
 -      unsigned int val;
 -      int ret;
 -
 -      regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);
 -      ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
 -                                     val, (val == 0),
 -                                     CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
 -      if (ret) {
 -              dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret);
 -              return ret;
 -      }
 -
 -      return 0;
 -}
 -
  static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56)
  {
        /* Wait for patching to complete */
@@@ -157,25 -173,25 +156,25 @@@ static int cs35l56_play_event(struct sn
        unsigned int val;
        int ret;
  
 -      dev_dbg(cs35l56->dev, "play: %d\n", event);
 +      dev_dbg(cs35l56->base.dev, "play: %d\n", event);
  
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
                /* Don't wait for ACK, we check in POST_PMU that it completed */
 -              return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
 +              return regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
                                    CS35L56_MBOX_CMD_AUDIO_PLAY);
        case SND_SOC_DAPM_POST_PMU:
                /* Wait for firmware to enter PS0 power state */
 -              ret = regmap_read_poll_timeout(cs35l56->regmap,
 +              ret = regmap_read_poll_timeout(cs35l56->base.regmap,
                                               CS35L56_TRANSDUCER_ACTUAL_PS,
                                               val, (val == CS35L56_PS0),
                                               CS35L56_PS0_POLL_US,
                                               CS35L56_PS0_TIMEOUT_US);
                if (ret)
 -                      dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret);
 +                      dev_err(cs35l56->base.dev, "PS0 wait failed: %d\n", ret);
                return ret;
        case SND_SOC_DAPM_POST_PMD:
 -              return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE);
 +              return cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE);
        default:
                return 0;
        }
@@@ -293,23 -309,109 +292,23 @@@ static int cs35l56_dsp_event(struct snd
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
  
 -      dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event);
 +      dev_dbg(cs35l56->base.dev, "%s: %d\n", __func__, event);
  
        return wm_adsp_event(w, kcontrol, event);
  }
  
 -irqreturn_t cs35l56_irq(int irq, void *data)
 -{
 -      struct cs35l56_private *cs35l56 = data;
 -      unsigned int status1 = 0, status8 = 0, status20 = 0;
 -      unsigned int mask1, mask8, mask20;
 -      unsigned int val;
 -      int rv;
 -
 -      irqreturn_t ret = IRQ_NONE;
 -
 -      if (!cs35l56->init_done)
 -              return IRQ_NONE;
 -
 -      mutex_lock(&cs35l56->irq_lock);
 -
 -      rv = pm_runtime_resume_and_get(cs35l56->dev);
 -      if (rv < 0) {
 -              dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv);
 -              goto err_unlock;
 -      }
 -
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val);
 -      if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
 -              dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n");
 -              goto err;
 -      }
 -
 -      /* Ack interrupts */
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1);
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1);
 -      status1 &= ~mask1;
 -      regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1);
 -
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8);
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8);
 -      status8 &= ~mask8;
 -      regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8);
 -
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20);
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20);
 -      status20 &= ~mask20;
 -      /* We don't want EINT20 but they default to unmasked: force mask */
 -      regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
 -
 -      dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8);
 -
 -      /* Check to see if unmasked bits are active */
 -      if (!status1 && !status8 && !status20)
 -              goto err;
 -
 -      if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
 -              dev_crit(cs35l56->dev, "Amp short error\n");
 -
 -      if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
 -              dev_crit(cs35l56->dev, "Overtemp error\n");
 -
 -      ret = IRQ_HANDLED;
 -
 -err:
 -      pm_runtime_put(cs35l56->dev);
 -err_unlock:
 -      mutex_unlock(&cs35l56->irq_lock);
 -
 -      return ret;
 -}
 -EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE);
 -
 -int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq)
 -{
 -      int ret;
 -
 -      if (!irq)
 -              return 0;
 -
 -      ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq,
 -                                      IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
 -                                      "cs35l56", cs35l56);
 -      if (!ret)
 -              cs35l56->irq = irq;
 -      else
 -              dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret);
 -
 -      return ret;
 -}
 -EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE);
 -
  static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
  {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);
        unsigned int val;
  
 -      dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt);
 +      dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt);
  
        switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
        case SND_SOC_DAIFMT_CBC_CFC:
                break;
        default:
 -              dev_err(cs35l56->dev, "Unsupported clock source mode\n");
 +              dev_err(cs35l56->base.dev, "Unsupported clock source mode\n");
                return -EINVAL;
        }
  
                cs35l56->tdm_mode = false;
                break;
        default:
 -              dev_err(cs35l56->dev, "Unsupported DAI format\n");
 +              dev_err(cs35l56->base.dev, "Unsupported DAI format\n");
                return -EINVAL;
        }
  
        case SND_SOC_DAIFMT_NB_NF:
                break;
        default:
 -              dev_err(cs35l56->dev, "Invalid clock invert\n");
 +              dev_err(cs35l56->base.dev, "Invalid clock invert\n");
                return -EINVAL;
        }
  
 -      regmap_update_bits(cs35l56->regmap,
 +      regmap_update_bits(cs35l56->base.regmap,
                           CS35L56_ASP1_CONTROL2,
                           CS35L56_ASP_FMT_MASK |
                           CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK,
                           val);
  
        /* Hi-Z DOUT in unused slots and when all TX are disabled */
 -      regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3,
 +      regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL3,
                           CS35L56_ASP1_DOUT_HIZ_CTRL_MASK,
                           CS35L56_ASP_UNUSED_HIZ_OFF_HIZ);
  
@@@ -382,7 -484,7 +381,7 @@@ static void cs35l56_set_asp_slot_positi
                channel_shift += 8;
        }
  
 -      regmap_write(cs35l56->regmap, reg, reg_val);
 +      regmap_write(cs35l56->base.regmap, reg, reg_val);
  }
  
  static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
  
        if ((slots == 0) || (slot_width == 0)) {
 -              dev_dbg(cs35l56->dev, "tdm config cleared\n");
 +              dev_dbg(cs35l56->base.dev, "tdm config cleared\n");
                cs35l56->asp_slot_width = 0;
                cs35l56->asp_slot_count = 0;
                return 0;
        }
  
        if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) {
 -              dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width);
 +              dev_err(cs35l56->base.dev, "tdm invalid slot width %d\n", slot_width);
                return -EINVAL;
        }
  
        /* More than 32 slots would give an unsupportable BCLK frequency */
        if (slots > 32) {
 -              dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots);
 +              dev_err(cs35l56->base.dev, "tdm invalid slot count %d\n", slots);
                return -EINVAL;
        }
  
        cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask);
        cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask);
  
 -      dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n",
 +      dev_dbg(cs35l56->base.dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n",
                cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask);
  
        return 0;
@@@ -441,8 -543,7 +440,8 @@@ static int cs35l56_asp_dai_hw_params(st
        else
                asp_width = asp_wl;
  
 -      dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate);
 +      dev_dbg(cs35l56->base.dev, "%s: wl=%d, width=%d, rate=%d",
 +              __func__, asp_wl, asp_width, rate);
  
        if (!cs35l56->sysclk_set) {
                unsigned int slots = cs35l56->asp_slot_count;
                bclk_freq = asp_width * slots * rate;
                freq_id = cs35l56_get_bclk_freq_id(bclk_freq);
                if (freq_id < 0) {
 -                      dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq);
 +                      dev_err(cs35l56->base.dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq);
                        return -EINVAL;
                }
  
 -              regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1,
 +              regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
                                   CS35L56_ASP_BCLK_FREQ_MASK,
                                   freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
        }
  
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 -              regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2,
 +              regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
                                   CS35L56_ASP_RX_WIDTH_MASK, asp_width <<
                                   CS35L56_ASP_RX_WIDTH_SHIFT);
 -              regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5,
 +              regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL5,
                                   CS35L56_ASP_RX_WL_MASK, asp_wl);
        } else {
 -              regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2,
 +              regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
                                   CS35L56_ASP_TX_WIDTH_MASK, asp_width <<
                                   CS35L56_ASP_TX_WIDTH_SHIFT);
 -              regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1,
 +              regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL1,
                                   CS35L56_ASP_TX_WL_MASK, asp_wl);
        }
  
@@@ -501,7 -602,7 +500,7 @@@ static int cs35l56_asp_dai_set_sysclk(s
        if (freq_id < 0)
                return freq_id;
  
 -      regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1,
 +      regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
                           CS35L56_ASP_BCLK_FREQ_MASK,
                           freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
        cs35l56->sysclk_set = true;
@@@ -544,9 -645,9 +543,9 @@@ static int cs35l56_sdw_dai_hw_params(st
        struct sdw_port_config pconfig;
        int ret;
  
 -      dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params));
 +      dev_dbg(cs35l56->base.dev, "%s: rate %d\n", __func__, params_rate(params));
  
 -      if (!cs35l56->init_done)
 +      if (!cs35l56->base.init_done)
                return -ENODEV;
  
        if (!sdw_stream)
@@@ -659,6 -760,67 +658,6 @@@ static struct snd_soc_dai_driver cs35l5
        }
  };
  
 -static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56)
 -{
 -      unsigned int reg;
 -      unsigned int val;
 -      int ret;
 -
 -      if (cs35l56->rev < CS35L56_REVID_B0)
 -              reg = CS35L56_DSP1_HALO_STATE_A1;
 -      else
 -              reg = CS35L56_DSP1_HALO_STATE;
 -
 -      ret = regmap_read_poll_timeout(cs35l56->regmap, reg,
 -                                     val,
 -                                     (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
 -                                     CS35L56_HALO_STATE_POLL_US,
 -                                     CS35L56_HALO_STATE_TIMEOUT_US);
 -
 -      if ((ret < 0) && (ret != -ETIMEDOUT)) {
 -              dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret);
 -              return ret;
 -      }
 -
 -      if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) {
 -              dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val);
 -              return -EIO;
 -      }
 -
 -      return 0;
 -}
 -
 -static inline void cs35l56_wait_min_reset_pulse(void)
 -{
 -      /* Satisfy minimum reset pulse width spec */
 -      usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
 -}
 -
 -static const struct reg_sequence cs35l56_system_reset_seq[] = {
 -      REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
 -};
 -
 -static void cs35l56_system_reset(struct cs35l56_private *cs35l56)
 -{
 -      cs35l56->soft_resetting = true;
 -
 -      /*
 -       * Must enter cache-only first so there can't be any more register
 -       * accesses other than the controlled system reset sequence below.
 -       */
 -      regcache_cache_only(cs35l56->regmap, true);
 -      regmap_multi_reg_write_bypassed(cs35l56->regmap,
 -                                      cs35l56_system_reset_seq,
 -                                      ARRAY_SIZE(cs35l56_system_reset_seq));
 -
 -      /* On SoundWire the registers won't be accessible until it re-enumerates. */
 -      if (cs35l56->sdw_peripheral)
 -              return;
 -
 -      usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400);
 -      regcache_cache_only(cs35l56->regmap, false);
 -}
 -
  static void cs35l56_secure_patch(struct cs35l56_private *cs35l56)
  {
        int ret;
        /* Use wm_adsp to load and apply the firmware patch and coefficient files */
        ret = wm_adsp_power_up(&cs35l56->dsp);
        if (ret)
 -              dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
 +              dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
        else
 -              cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_REINIT);
 +              cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
  }
  
  static void cs35l56_patch(struct cs35l56_private *cs35l56)
  {
 -      unsigned int reg;
 -      unsigned int val;
        int ret;
  
        /*
                flush_work(&cs35l56->sdw_irq_work);
        }
  
 -      ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN);
 +      ret = cs35l56_firmware_shutdown(&cs35l56->base);
        if (ret)
                goto err;
  
 -      if (cs35l56->rev < CS35L56_REVID_B0)
 -              reg = CS35L56_DSP1_PM_CUR_STATE_A1;
 -      else
 -              reg = CS35L56_DSP1_PM_CUR_STATE;
 -
 -      ret = regmap_read_poll_timeout(cs35l56->regmap, reg,
 -                                     val, (val == CS35L56_HALO_STATE_SHUTDOWN),
 -                                     CS35L56_HALO_STATE_POLL_US,
 -                                     CS35L56_HALO_STATE_TIMEOUT_US);
 -      if (ret < 0)
 -              dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
 -                      val, ret);
 -
        /* Use wm_adsp to load and apply the firmware patch and coefficient files */
        ret = wm_adsp_power_up(&cs35l56->dsp);
        if (ret) {
 -              dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
 +              dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
                goto err;
        }
  
 -      mutex_lock(&cs35l56->irq_lock);
 +      mutex_lock(&cs35l56->base.irq_lock);
  
        init_completion(&cs35l56->init_completion);
  
 -      cs35l56_system_reset(cs35l56);
 +      cs35l56->soft_resetting = true;
 +      cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral);
  
        if (cs35l56->sdw_peripheral) {
                /*
                 */
                if (!wait_for_completion_timeout(&cs35l56->init_completion,
                                                 msecs_to_jiffies(5000))) {
 -                      dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__);
 +                      dev_err(cs35l56->base.dev, "%s: init_completion timed out (SDW)\n",
 +                              __func__);
                        goto err_unlock;
                }
        } else if (cs35l56_init(cs35l56)) {
                goto err_unlock;
        }
  
 -      regmap_clear_bits(cs35l56->regmap, CS35L56_PROTECTION_STATUS, CS35L56_FIRMWARE_MISSING);
 -      cs35l56->fw_patched = true;
 +      regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS,
 +                        CS35L56_FIRMWARE_MISSING);
 +      cs35l56->base.fw_patched = true;
  
  err_unlock:
 -      mutex_unlock(&cs35l56->irq_lock);
 +      mutex_unlock(&cs35l56->base.irq_lock);
  err:
        /* Re-enable SoundWire interrupts */
        if (cs35l56->sdw_peripheral) {
@@@ -744,10 -918,10 +743,10 @@@ static void cs35l56_dsp_work(struct wor
                                                       struct cs35l56_private,
                                                       dsp_work);
  
 -      if (!cs35l56->init_done)
 +      if (!cs35l56->base.init_done)
                return;
  
 -      pm_runtime_get_sync(cs35l56->dev);
 +      pm_runtime_get_sync(cs35l56->base.dev);
  
        /*
         * When the device is running in secure mode the firmware files can
         * shutdown the firmware to apply them and can use the lower cost
         * reinit sequence instead.
         */
 -      if (cs35l56->secured)
 +      if (cs35l56->base.secured)
                cs35l56_secure_patch(cs35l56);
        else
                cs35l56_patch(cs35l56);
  
 -      pm_runtime_mark_last_busy(cs35l56->dev);
 -      pm_runtime_put_autosuspend(cs35l56->dev);
 +      pm_runtime_mark_last_busy(cs35l56->base.dev);
 +      pm_runtime_put_autosuspend(cs35l56->base.dev);
  }
  
  static int cs35l56_component_probe(struct snd_soc_component *component)
  
        if (!wait_for_completion_timeout(&cs35l56->init_completion,
                                         msecs_to_jiffies(5000))) {
 -              dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__);
 +              dev_err(cs35l56->base.dev, "%s: init_completion timed out\n", __func__);
                return -ENODEV;
        }
  
        cs35l56->component = component;
        wm_adsp2_component_probe(&cs35l56->dsp, component);
  
 -      debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->init_done);
 -      debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->can_hibernate);
 -      debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->fw_patched);
 +      debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done);
 +      debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate);
 +      debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched);
  
        queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work);
  
@@@ -834,18 -1008,171 +833,18 @@@ static const struct snd_soc_component_d
        .suspend_bias_off = 1, /* see cs35l56_system_resume() */
  };
  
 -static const struct reg_sequence cs35l56_hibernate_seq[] = {
 -      /* This must be the last register access */
 -      REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW),
 -};
 -
 -static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
 -      REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
 -};
 -
 -int cs35l56_runtime_suspend(struct device *dev)
 +static int __maybe_unused cs35l56_runtime_suspend_i2c_spi(struct device *dev)
  {
        struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
 -      unsigned int val;
 -      int ret;
 -
 -      if (!cs35l56->init_done)
 -              return 0;
  
 -      /* Firmware must have entered a power-save state */
 -      ret = regmap_read_poll_timeout(cs35l56->regmap,
 -                                     CS35L56_TRANSDUCER_ACTUAL_PS,
 -                                     val, (val >= CS35L56_PS3),
 -                                     CS35L56_PS3_POLL_US,
 -                                     CS35L56_PS3_TIMEOUT_US);
 -      if (ret)
 -              dev_warn(cs35l56->dev, "PS3 wait failed: %d\n", ret);
 -
 -      /* Clear BOOT_DONE so it can be used to detect a reboot */
 -      regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
 -
 -      if (!cs35l56->can_hibernate) {
 -              regcache_cache_only(cs35l56->regmap, true);
 -              dev_dbg(dev, "Suspended: no hibernate");
 -
 -              return 0;
 -      }
 -
 -      /*
 -       * Enable auto-hibernate. If it is woken by some other wake source
 -       * it will automatically return to hibernate.
 -       */
 -      cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
 -
 -      /*
 -       * Must enter cache-only first so there can't be any more register
 -       * accesses other than the controlled hibernate sequence below.
 -       */
 -      regcache_cache_only(cs35l56->regmap, true);
 -
 -      regmap_multi_reg_write_bypassed(cs35l56->regmap,
 -                                      cs35l56_hibernate_seq,
 -                                      ARRAY_SIZE(cs35l56_hibernate_seq));
 -
 -      dev_dbg(dev, "Suspended: hibernate");
 -
 -      return 0;
 +      return cs35l56_runtime_suspend_common(&cs35l56->base);
  }
 -EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend, SND_SOC_CS35L56_CORE);
  
  static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev)
  {
        struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
  
 -      if (!cs35l56->init_done)
 -              return 0;
 -
 -      return cs35l56_runtime_resume_common(cs35l56);
 -}
 -
 -int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56)
 -{
 -      unsigned int val;
 -      int ret;
 -
 -      if (!cs35l56->can_hibernate)
 -              goto out_sync;
 -
 -      if (!cs35l56->sdw_peripheral) {
 -              /*
 -               * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C.
 -               * Must be done before releasing cache-only.
 -               */
 -              regmap_multi_reg_write_bypassed(cs35l56->regmap,
 -                                              cs35l56_hibernate_wake_seq,
 -                                              ARRAY_SIZE(cs35l56_hibernate_wake_seq));
 -
 -              usleep_range(CS35L56_CONTROL_PORT_READY_US,
 -                           CS35L56_CONTROL_PORT_READY_US + 400);
 -      }
 -
 -out_sync:
 -      regcache_cache_only(cs35l56->regmap, false);
 -
 -      ret = cs35l56_wait_for_firmware_boot(cs35l56);
 -      if (ret) {
 -              dev_err(cs35l56->dev, "Hibernate wake failed: %d\n", ret);
 -              goto err;
 -      }
 -
 -      ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
 -      if (ret)
 -              goto err;
 -
 -      /* BOOT_DONE will be 1 if the amp reset */
 -      regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val);
 -      if (val & CS35L56_OTP_BOOT_DONE_MASK) {
 -              dev_dbg(cs35l56->dev, "Registers reset in suspend\n");
 -              regcache_mark_dirty(cs35l56->regmap);
 -      }
 -
 -      regcache_sync(cs35l56->regmap);
 -
 -      dev_dbg(cs35l56->dev, "Resumed");
 -
 -      return 0;
 -
 -err:
 -      regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
 -                   CS35L56_MBOX_CMD_HIBERNATE_NOW);
 -
 -      regcache_cache_only(cs35l56->regmap, true);
 -
 -      return ret;
 -}
 -EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE);
 -
 -static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56)
 -{
 -      unsigned int val;
 -      int ret;
 -
 -      /* Nothing to re-patch if we haven't done any patching yet. */
 -      if (!cs35l56->fw_patched)
 -              return false;
 -
 -      /*
 -       * If we have control of RESET we will have asserted it so the firmware
 -       * will need re-patching.
 -       */
 -      if (cs35l56->reset_gpio)
 -              return true;
 -
 -      /*
 -       * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
 -       * can't be used here to test for memory retention.
 -       * Assume that tuning must be re-loaded.
 -       */
 -      if (cs35l56->secured)
 -              return true;
 -
 -      ret = pm_runtime_resume_and_get(cs35l56->dev);
 -      if (ret) {
 -              dev_err(cs35l56->dev, "Failed to runtime_get: %d\n", ret);
 -              return ret;
 -      }
 -
 -      ret = regmap_read(cs35l56->regmap, CS35L56_PROTECTION_STATUS, &val);
 -      if (ret)
 -              dev_err(cs35l56->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
 -      else
 -              ret = !!(val & CS35L56_FIRMWARE_MISSING);
 -
 -      pm_runtime_put_autosuspend(cs35l56->dev);
 -
 -      return ret;
 +      return cs35l56_runtime_resume_common(&cs35l56->base, false);
  }
  
  int cs35l56_system_suspend(struct device *dev)
         * clear it. Prevent this race by temporarily disabling the parent irq
         * until we reach _no_irq.
         */
 -      if (cs35l56->irq)
 -              disable_irq(cs35l56->irq);
 +      if (cs35l56->base.irq)
 +              disable_irq(cs35l56->base.irq);
  
        return pm_runtime_force_suspend(dev);
  }
@@@ -881,8 -1208,8 +880,8 @@@ int cs35l56_system_suspend_late(struct 
         * RESET is usually shared by all amps so it must not be asserted until
         * all driver instances have done their suspend() stage.
         */
 -      if (cs35l56->reset_gpio) {
 -              gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
 +      if (cs35l56->base.reset_gpio) {
 +              gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
                cs35l56_wait_min_reset_pulse();
        }
  
@@@ -899,8 -1226,8 +898,8 @@@ int cs35l56_system_suspend_no_irq(struc
        dev_dbg(dev, "system_suspend_no_irq\n");
  
        /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */
 -      if (cs35l56->irq)
 -              enable_irq(cs35l56->irq);
 +      if (cs35l56->base.irq)
 +              enable_irq(cs35l56->base.irq);
  
        return 0;
  }
@@@ -919,8 -1246,8 +918,8 @@@ int cs35l56_system_resume_no_irq(struc
         * clear it, until it has fully resumed. Prevent this race by temporarily
         * disabling the parent irq until we complete resume().
         */
 -      if (cs35l56->irq)
 -              disable_irq(cs35l56->irq);
 +      if (cs35l56->base.irq)
 +              disable_irq(cs35l56->base.irq);
  
        return 0;
  }
@@@ -934,8 -1261,8 +933,8 @@@ int cs35l56_system_resume_early(struct 
        dev_dbg(dev, "system_resume_early\n");
  
        /* Ensure a spec-compliant RESET pulse. */
 -      if (cs35l56->reset_gpio) {
 -              gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
 +      if (cs35l56->base.reset_gpio) {
 +              gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
                cs35l56_wait_min_reset_pulse();
        }
  
        }
  
        /* Release shared RESET before drivers start resume(). */
 -      gpiod_set_value_cansleep(cs35l56->reset_gpio, 1);
 +      gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
  
        return 0;
  }
@@@ -962,8 -1289,8 +961,8 @@@ int cs35l56_system_resume(struct devic
  
        /* Undo pm_runtime_force_suspend() before re-enabling the irq */
        ret = pm_runtime_force_resume(dev);
 -      if (cs35l56->irq)
 -              enable_irq(cs35l56->irq);
 +      if (cs35l56->base.irq)
 +              enable_irq(cs35l56->base.irq);
  
        if (ret)
                return ret;
        if (!cs35l56->component)
                return 0;
  
 -      ret = cs35l56_is_fw_reload_needed(cs35l56);
 -      dev_dbg(cs35l56->dev, "fw_reload_needed: %d\n", ret);
 +      ret = cs35l56_is_fw_reload_needed(&cs35l56->base);
 +      dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret);
        if (ret < 1)
                return ret;
  
 -      cs35l56->fw_patched = false;
 +      cs35l56->base.fw_patched = false;
        queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work);
  
        /*
@@@ -1001,42 -1328,47 +1000,38 @@@ static int cs35l56_dsp_init(struct cs35
        INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work);
  
        dsp = &cs35l56->dsp;
 +      cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp);
        dsp->part = "cs35l56";
 -      dsp->cs_dsp.num = 1;
 -      dsp->cs_dsp.type = WMFW_HALO;
 -      dsp->cs_dsp.rev = 0;
        dsp->fw = 12;
 -      dsp->cs_dsp.dev = cs35l56->dev;
 -      dsp->cs_dsp.regmap = cs35l56->regmap;
 -      dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE;
 -      dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
 -      dsp->cs_dsp.mem = cs35l56_dsp1_regions;
 -      dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
 -      dsp->cs_dsp.no_core_startstop = true;
        dsp->wmfw_optional = true;
  
 -      dev_dbg(cs35l56->dev, "DSP system name: '%s'\n", dsp->system_name);
 +      dev_dbg(cs35l56->base.dev, "DSP system name: '%s'\n", dsp->system_name);
  
        ret = wm_halo_init(dsp);
        if (ret != 0) {
 -              dev_err(cs35l56->dev, "wm_halo_init failed\n");
 +              dev_err(cs35l56->base.dev, "wm_halo_init failed\n");
                return ret;
        }
  
        return 0;
  }
  
- static int cs35l56_acpi_get_name(struct cs35l56_private *cs35l56)
+ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56)
  {
-       acpi_handle handle = ACPI_HANDLE(cs35l56->base.dev);
-       const char *sub;
 -      struct device *dev = cs35l56->dev;
++      struct device *dev = cs35l56->base.dev;
+       const char *prop;
+       int ret;
  
-       /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */
-       if (!handle)
+       ret = device_property_read_string(dev, "cirrus,firmware-uid", &prop);
+       /* If bad sw node property, return 0 and fallback to legacy firmware path */
+       if (ret < 0)
                return 0;
  
-       sub = acpi_get_subsystem_id(handle);
-       if (IS_ERR(sub)) {
-               /* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */
-               if (PTR_ERR(sub) == -ENODATA)
-                       return 0;
-               else
-                       return PTR_ERR(sub);
-       }
+       cs35l56->dsp.system_name = devm_kstrdup(dev, prop, GFP_KERNEL);
+       if (cs35l56->dsp.system_name == NULL)
+               return -ENOMEM;
  
-       cs35l56->dsp.system_name = sub;
-       dev_dbg(cs35l56->base.dev, "Subsystem ID: %s\n", cs35l56->dsp.system_name);
+       dev_dbg(dev, "Firmware UID: %s\n", cs35l56->dsp.system_name);
  
        return 0;
  }
@@@ -1046,63 -1378,62 +1041,63 @@@ int cs35l56_common_probe(struct cs35l56
        int ret;
  
        init_completion(&cs35l56->init_completion);
 -      mutex_init(&cs35l56->irq_lock);
 +      mutex_init(&cs35l56->base.irq_lock);
  
 -      dev_set_drvdata(cs35l56->dev, cs35l56);
 +      dev_set_drvdata(cs35l56->base.dev, cs35l56);
  
        cs35l56_fill_supply_names(cs35l56->supplies);
 -      ret = devm_regulator_bulk_get(cs35l56->dev, ARRAY_SIZE(cs35l56->supplies),
 +      ret = devm_regulator_bulk_get(cs35l56->base.dev, ARRAY_SIZE(cs35l56->supplies),
                                      cs35l56->supplies);
        if (ret != 0)
 -              return dev_err_probe(cs35l56->dev, ret, "Failed to request supplies\n");
 +              return dev_err_probe(cs35l56->base.dev, ret, "Failed to request supplies\n");
  
        /* Reset could be controlled by the BIOS or shared by multiple amps */
 -      cs35l56->reset_gpio = devm_gpiod_get_optional(cs35l56->dev, "reset", GPIOD_OUT_LOW);
 -      if (IS_ERR(cs35l56->reset_gpio)) {
 -              ret = PTR_ERR(cs35l56->reset_gpio);
 +      cs35l56->base.reset_gpio = devm_gpiod_get_optional(cs35l56->base.dev, "reset",
 +                                                         GPIOD_OUT_LOW);
 +      if (IS_ERR(cs35l56->base.reset_gpio)) {
 +              ret = PTR_ERR(cs35l56->base.reset_gpio);
                /*
                 * If RESET is shared the first amp to probe will grab the reset
                 * line and reset all the amps
                 */
                if (ret != -EBUSY)
 -                      return dev_err_probe(cs35l56->dev, ret, "Failed to get reset GPIO\n");
 +                      return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n");
  
 -              dev_info(cs35l56->dev, "Reset GPIO busy, assume shared reset\n");
 -              cs35l56->reset_gpio = NULL;
 +              dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n");
 +              cs35l56->base.reset_gpio = NULL;
        }
  
        ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
        if (ret != 0)
 -              return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n");
 +              return dev_err_probe(cs35l56->base.dev, ret, "Failed to enable supplies\n");
  
 -      if (cs35l56->reset_gpio) {
 +      if (cs35l56->base.reset_gpio) {
                cs35l56_wait_min_reset_pulse();
 -              gpiod_set_value_cansleep(cs35l56->reset_gpio, 1);
 +              gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
        }
  
-       ret = cs35l56_acpi_get_name(cs35l56);
+       ret = cs35l56_get_firmware_uid(cs35l56);
        if (ret != 0)
                goto err;
  
        ret = cs35l56_dsp_init(cs35l56);
        if (ret < 0) {
 -              dev_err_probe(cs35l56->dev, ret, "DSP init failed\n");
 +              dev_err_probe(cs35l56->base.dev, ret, "DSP init failed\n");
                goto err;
        }
  
 -      ret = devm_snd_soc_register_component(cs35l56->dev,
 +      ret = devm_snd_soc_register_component(cs35l56->base.dev,
                                              &soc_component_dev_cs35l56,
                                              cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
        if (ret < 0) {
 -              dev_err_probe(cs35l56->dev, ret, "Register codec failed\n");
 +              dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
                goto err;
        }
  
        return 0;
  
  err:
 -      gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
 +      gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
        regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
  
        return ret;
@@@ -1112,6 -1443,7 +1107,6 @@@ EXPORT_SYMBOL_NS_GPL(cs35l56_common_pro
  int cs35l56_init(struct cs35l56_private *cs35l56)
  {
        int ret;
 -      unsigned int devid, revid, otpid, secured;
  
        /*
         * Check whether the actions associated with soft reset or one time
        if (cs35l56->soft_resetting)
                goto post_soft_reset;
  
 -      if (cs35l56->init_done)
 +      if (cs35l56->base.init_done)
                return 0;
  
 -      pm_runtime_set_autosuspend_delay(cs35l56->dev, 100);
 -      pm_runtime_use_autosuspend(cs35l56->dev);
 -      pm_runtime_set_active(cs35l56->dev);
 -      pm_runtime_enable(cs35l56->dev);
 -
 -      /*
 -       * If the system is not using a reset_gpio then issue a
 -       * dummy read to force a wakeup.
 -       */
 -      if (!cs35l56->reset_gpio)
 -              regmap_read(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid);
 -
 -      /* Wait for control port to be ready (datasheet tIRS). */
 -      usleep_range(CS35L56_CONTROL_PORT_READY_US,
 -                   CS35L56_CONTROL_PORT_READY_US + 400);
 -
 -      /*
 -       * The HALO_STATE register is in different locations on Ax and B0
 -       * devices so the REVID needs to be determined before waiting for the
 -       * firmware to boot.
 -       */
 -      ret = regmap_read(cs35l56->regmap, CS35L56_REVID, &revid);
 -      if (ret < 0) {
 -              dev_err(cs35l56->dev, "Get Revision ID failed\n");
 -              return ret;
 -      }
 -      cs35l56->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
 -
 -      ret = cs35l56_wait_for_firmware_boot(cs35l56);
 -      if (ret)
 -              return ret;
 -
 -      ret = regmap_read(cs35l56->regmap, CS35L56_DEVID, &devid);
 -      if (ret < 0) {
 -              dev_err(cs35l56->dev, "Get Device ID failed\n");
 -              return ret;
 -      }
 -      devid &= CS35L56_DEVID_MASK;
 -
 -      switch (devid) {
 -      case 0x35A56:
 -              break;
 -      default:
 -              dev_err(cs35l56->dev, "Unknown device %x\n", devid);
 -              return ret;
 -      }
 -
 -      ret = regmap_read(cs35l56->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
 -      if (ret) {
 -              dev_err(cs35l56->dev, "Get Secure status failed\n");
 -              return ret;
 -      }
 -
 -      /* When any bus is restricted treat the device as secured */
 -      if (secured & CS35L56_RESTRICTED_MASK)
 -              cs35l56->secured = true;
 +      pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 100);
 +      pm_runtime_use_autosuspend(cs35l56->base.dev);
 +      pm_runtime_set_active(cs35l56->base.dev);
 +      pm_runtime_enable(cs35l56->base.dev);
  
 -      ret = regmap_read(cs35l56->regmap, CS35L56_OTPID, &otpid);
 -      if (ret < 0) {
 -              dev_err(cs35l56->dev, "Get OTP ID failed\n");
 +      ret = cs35l56_hw_init(&cs35l56->base);
 +      if (ret < 0)
                return ret;
 -      }
 -
 -      dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n",
 -               cs35l56->secured ? "s" : "", cs35l56->rev, otpid);
  
        /* Populate the DSP information with the revision and security state */
 -      cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x",
 -                                         cs35l56->secured ? "s" : "", cs35l56->rev);
 +      cs35l56->dsp.part = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "cs35l56%s-%02x",
 +                                         cs35l56->base.secured ? "s" : "", cs35l56->base.rev);
        if (!cs35l56->dsp.part)
                return -ENOMEM;
  
 -      /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
 -      regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
 -      regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1,
 -                         CS35L56_AMP_SHORT_ERR_EINT1_MASK,
 -                         0);
 -      regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_8,
 -                         CS35L56_TEMP_ERR_EINT1_MASK,
 -                         0);
 -
 -      if (!cs35l56->reset_gpio) {
 -              dev_dbg(cs35l56->dev, "No reset gpio: using soft reset\n");
 -              cs35l56_system_reset(cs35l56);
 +      if (!cs35l56->base.reset_gpio) {
 +              dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n");
 +              cs35l56->soft_resetting = true;
 +              cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral);
                if (cs35l56->sdw_peripheral) {
                        /* Keep alive while we wait for re-enumeration */
 -                      pm_runtime_get_noresume(cs35l56->dev);
 +                      pm_runtime_get_noresume(cs35l56->base.dev);
                        return 0;
                }
        }
@@@ -1154,30 -1551,29 +1149,30 @@@ post_soft_reset
                cs35l56->soft_resetting = false;
  
                /* Done re-enumerating after one-time init so release the keep-alive */
 -              if (cs35l56->sdw_peripheral && !cs35l56->init_done)
 -                      pm_runtime_put_noidle(cs35l56->dev);
 +              if (cs35l56->sdw_peripheral && !cs35l56->base.init_done)
 +                      pm_runtime_put_noidle(cs35l56->base.dev);
  
 -              regcache_mark_dirty(cs35l56->regmap);
 -              ret = cs35l56_wait_for_firmware_boot(cs35l56);
 +              regcache_mark_dirty(cs35l56->base.regmap);
 +              ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
                if (ret)
                        return ret;
  
 -              dev_dbg(cs35l56->dev, "Firmware rebooted after soft reset\n");
 +              dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n");
        }
  
        /* Disable auto-hibernate so that runtime_pm has control */
 -      ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
 +      ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
        if (ret)
                return ret;
  
 -      /* Populate soft registers in the regmap cache */
 -      cs35l56_reread_firmware_registers(cs35l56->dev, cs35l56->regmap);
 +      ret = cs35l56_set_patch(&cs35l56->base);
 +      if (ret)
 +              return ret;
  
        /* Registers could be dirty after soft reset or SoundWire enumeration */
 -      regcache_sync(cs35l56->regmap);
 +      regcache_sync(cs35l56->base.regmap);
  
 -      cs35l56->init_done = true;
 +      cs35l56->base.init_done = true;
        complete(&cs35l56->init_completion);
  
        return 0;
@@@ -1186,32 -1582,30 +1181,30 @@@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_
  
  void cs35l56_remove(struct cs35l56_private *cs35l56)
  {
 -      cs35l56->init_done = false;
 +      cs35l56->base.init_done = false;
  
        /*
         * WAKE IRQs unmask if CS35L56 hibernates so free the handler to
         * prevent it racing with remove().
         */
 -      if (cs35l56->irq)
 -              devm_free_irq(cs35l56->dev, cs35l56->irq, cs35l56);
 +      if (cs35l56->base.irq)
 +              devm_free_irq(cs35l56->base.dev, cs35l56->base.irq, &cs35l56->base);
  
        flush_workqueue(cs35l56->dsp_wq);
        destroy_workqueue(cs35l56->dsp_wq);
  
 -      pm_runtime_suspend(cs35l56->dev);
 -      pm_runtime_disable(cs35l56->dev);
 +      pm_runtime_suspend(cs35l56->base.dev);
 +      pm_runtime_disable(cs35l56->base.dev);
  
 -      regcache_cache_only(cs35l56->regmap, true);
 +      regcache_cache_only(cs35l56->base.regmap, true);
  
-       kfree(cs35l56->dsp.system_name);
 -      gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
 +      gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
        regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
  }
  EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE);
  
  const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = {
 -      SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL)
 +      SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend_i2c_spi, cs35l56_runtime_resume_i2c_spi, NULL)
        SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend, cs35l56_system_resume)
        LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early)
        NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_no_irq, cs35l56_system_resume_no_irq)
index 7e5eb13af4280eeb4df875a84f3a979549919952,65e497b455d34a003af1c9043fa4c25ed4876829..a8f347f1affbdc44d63aa3612850e5fc6f4795c7
@@@ -27,9 -27,9 +27,9 @@@
   * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
   * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
   */
 -#define NR_SUPPORTED_MCLK_LRCK_RATIOS 6
 +#define NR_SUPPORTED_MCLK_LRCK_RATIOS ARRAY_SIZE(supported_mclk_lrck_ratios)
  static const unsigned int supported_mclk_lrck_ratios[] = {
 -      256, 384, 400, 512, 768, 1024
 +      256, 384, 400, 500, 512, 768, 1024
  };
  
  struct es8316_priv {
@@@ -153,7 -153,7 +153,7 @@@ static const char * const es8316_dmic_t
                "dmic data at high level",
                "dmic data at low level",
  };
- static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
+ static const unsigned int es8316_dmic_values[] = { 0, 2, 3 };
  static const struct soc_enum es8316_dmic_src_enum =
        SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
                              ARRAY_SIZE(es8316_dmic_txt),
@@@ -494,7 -494,6 +494,7 @@@ static int es8316_pcm_hw_params(struct 
                bclk_divider /= 20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
 +      case SNDRV_PCM_FORMAT_S24_3LE:
                wordlen = ES8316_SERDATA2_LEN_24;
                bclk_divider /= 24;
                break;
index a9416bd163e868fef33337c13cec348176c4b0f3,e9103ffb3f504dca934cf103903ea670d8c8294a..a38ec58622145750a0a61f21b8708823f2e75997
@@@ -175,7 -175,7 +175,7 @@@ static int rt722_sdca_update_status(str
                 * This also could sync with the cache value as the rt722_sdca_jack_init set.
                 */
                        sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1,
 -                              SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6);
 +                              SDW_SCP_SDCA_INTMASK_SDCA_6);
                        sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2,
                                SDW_SCP_SDCA_INTMASK_SDCA_8);
                }
@@@ -463,8 -463,16 +463,16 @@@ static int __maybe_unused rt722_sdca_de
        if (!rt722->first_hw_init)
                return 0;
  
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt722->disable_irq == true) {
+                       mutex_lock(&rt722->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt722->disable_irq = false;
+                       mutex_unlock(&rt722->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
  
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT722_PROBE_TIMEOUT));
index ac4e1654a9676cb6779598a7942d79441e458354,f2baee7c332e9b1475b1c240ea371ab5421ae1c5..60319b468fb2684749a95b01078e105339d22e5a
@@@ -2148,7 -2148,7 +2148,7 @@@ static const struct regmap_config wm890
        .volatile_reg = wm8904_volatile_register,
        .readable_reg = wm8904_readable_register,
  
 -      .cache_type = REGCACHE_RBTREE,
 +      .cache_type = REGCACHE_MAPLE,
        .reg_defaults = wm8904_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
  };
@@@ -2308,6 -2308,9 +2308,9 @@@ static int wm8904_i2c_probe(struct i2c_
        regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0,
                            WM8904_POBCTRL, 0);
  
+       /* Fill the cache for the ADC test register */
+       regmap_read(wm8904->regmap, WM8904_ADC_TEST_0, &val);
        /* Can leave the device powered off until we need it */
        regcache_cache_only(wm8904->regmap, true);
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
index 95e639711ebae5a71f86f03264cdbf0ebd16bbd2,3fd26f2cdd60f3e4d4baabc2ed84ea3f74f5c913..95bb8b10494ad994b2ece5edabd2a7ca230d988d
@@@ -514,10 -514,6 +514,10 @@@ static int spdif_set_sample_rate(struc
        int ret;
  
        switch (sample_rate) {
 +      case 22050:
 +              rate = SPDIF_TXRATE_22050;
 +              csfs = IEC958_AES3_CON_FS_22050;
 +              break;
        case 32000:
                rate = SPDIF_TXRATE_32000;
                csfs = IEC958_AES3_CON_FS_32000;
@@@ -755,6 -751,8 +755,8 @@@ static int fsl_spdif_trigger(struct snd
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0);
                regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0);
+               regmap_write(regmap, REG_SPDIF_STL, 0x0);
+               regmap_write(regmap, REG_SPDIF_STR, 0x0);
                break;
        default:
                return -EINVAL;
@@@ -1426,7 -1424,7 +1428,7 @@@ static u32 fsl_spdif_txclk_caldiv(struc
                                struct clk *clk, u64 savesub,
                                enum spdif_txrate index, bool round)
  {
 -      static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
 +      static const u32 rate[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400,
                                    192000, };
        bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
        u64 rate_ideal, rate_actual, sub;
@@@ -1487,7 -1485,7 +1489,7 @@@ out
  static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
                                enum spdif_txrate index)
  {
 -      static const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400,
 +      static const u32 rate[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400,
                                    192000, };
        struct platform_device *pdev = spdif_priv->pdev;
        struct device *dev = &pdev->dev;
diff --combined sound/soc/soc-pcm.c
index ae02d1d80c8851cddef6f1974f18b96e3b9082d3,3aa6b988cb4b492faf801434302cc28f844adf6c..eb07238768511a7c7478a6a2556e5a72f0b52ec0
@@@ -38,6 -38,7 +38,7 @@@ static inline int _soc_pcm_ret(struct s
        switch (ret) {
        case -EPROBE_DEFER:
        case -ENOTSUPP:
+       case -EINVAL:
                break;
        default:
                dev_err(rtd->dev,
@@@ -2466,8 -2467,11 +2467,11 @@@ static int dpcm_fe_dai_prepare(struct s
  
        /* there is no point preparing this FE if there are no BEs */
        if (list_empty(&fe->dpcm[stream].be_clients)) {
-               dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
-                               fe->dai_link->name);
+               /* dev_err_once() for visibility, dev_dbg() for debugging UCM profiles */
+               dev_err_once(fe->dev, "ASoC: no backend DAIs enabled for %s, possibly missing ALSA mixer-based routing or UCM profile\n",
+                            fe->dai_link->name);
+               dev_dbg(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
+                       fe->dai_link->name);
                ret = -EINVAL;
                goto out;
        }
@@@ -2973,8 -2977,8 +2977,8 @@@ int soc_new_pcm(struct snd_soc_pcm_runt
                        rtd->ops.ioctl          = snd_soc_pcm_component_ioctl;
                if (drv->sync_stop)
                        rtd->ops.sync_stop      = snd_soc_pcm_component_sync_stop;
 -              if (drv->copy_user)
 -                      rtd->ops.copy_user      = snd_soc_pcm_component_copy_user;
 +              if (drv->copy)
 +                      rtd->ops.copy           = snd_soc_pcm_component_copy;
                if (drv->page)
                        rtd->ops.page           = snd_soc_pcm_component_page;
                if (drv->mmap)