Merge branch 'asoc-5.2' into asoc-5.3
authorMark Brown <broonie@kernel.org>
Thu, 6 Jun 2019 21:44:24 +0000 (22:44 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 6 Jun 2019 21:44:24 +0000 (22:44 +0100)
1  2 
sound/hda/ext/hdac_ext_bus.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/cht_bsw_nau8824.c
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/soc-core.c
sound/soc/sof/intel/hda.c
sound/soc/sunxi/sun4i-i2s.c

index c203af71a0995f76842367d25b299bc6eecef279,08cc0ce3b9244ed16ccc4c30b7935c9bfd048064..f33ba58b753c30283230f65e443da5293ac394c1
@@@ -104,7 -104,10 +104,7 @@@ int snd_hdac_ext_bus_init(struct hdac_b
                return ret;
  
        bus->ext_ops = ext_ops;
 -      INIT_LIST_HEAD(&bus->hlink_list);
        bus->idx = idx++;
 -
 -      mutex_init(&bus->lock);
        bus->cmd_dma_state = true;
  
        return 0;
@@@ -170,7 -173,6 +170,6 @@@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_devi
  void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev)
  {
        snd_hdac_device_exit(hdev);
-       kfree(hdev);
  }
  EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
  
index b56f9230d1bcc95feae5174fc34caa0d51ae4826,128b57932a924a4f7a41e96961493c9eb61be506..43cea6f1e748e31f92bdfeb66c0801f75bc76db7
@@@ -30,6 -30,9 +30,6 @@@
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
 -#include <asm/cpu_device_id.h>
 -#include <asm/intel-family.h>
 -#include <asm/platform_sst_audio.h>
  #include <sound/jack.h>
  #include <sound/pcm.h>
  #include <sound/pcm_params.h>
@@@ -37,7 -40,6 +37,7 @@@
  #include <sound/soc-acpi.h>
  #include "../atom/sst-atom-controls.h"
  #include "../common/sst-dsp.h"
 +#include "../common/soc-intel-quirks.h"
  
  /* jd-inv + terminating entry */
  #define MAX_NO_PROPS 2
@@@ -307,43 -309,32 +307,43 @@@ static const struct snd_soc_ops byt_cht
        .startup = byt_cht_es8316_aif1_startup,
  };
  
 +SND_SOC_DAILINK_DEF(dummy,
 +      DAILINK_COMP_ARRAY(COMP_DUMMY()));
 +
 +SND_SOC_DAILINK_DEF(media,
 +      DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(deepbuffer,
 +      DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(ssp2_port,
 +      DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 +SND_SOC_DAILINK_DEF(ssp2_codec,
 +      DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8316:00", "ES8316 HiFi")));
 +
 +SND_SOC_DAILINK_DEF(platform,
 +      DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 +
  static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
        [MERR_DPCM_AUDIO] = {
                .name = "Audio Port",
                .stream_name = "Audio",
 -              .cpu_dai_name = "media-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &byt_cht_es8316_aif1_ops,
 +              SND_SOC_DAILINK_REG(media, dummy, platform),
        },
  
        [MERR_DPCM_DEEP_BUFFER] = {
                .name = "Deep-Buffer Audio Port",
                .stream_name = "Deep-Buffer Audio",
 -              .cpu_dai_name = "deepbuffer-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .ops = &byt_cht_es8316_aif1_ops,
 +              SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
        },
  
                /* back ends */
                 */
                .name = "SSP2-Codec",
                .id = 0,
 -              .cpu_dai_name = "ssp2-port",
 -              .platform_name = "sst-mfld-platform",
                .no_pcm = 1,
 -              .codec_dai_name = "ES8316 HiFi",
 -              .codec_name = "i2c-ESSX8316:00",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                                | SND_SOC_DAIFMT_CBS_CFS,
                .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .init = byt_cht_es8316_init,
 +              SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
  };
  
@@@ -436,6 -430,11 +436,6 @@@ static struct snd_soc_card byt_cht_es83
        .resume_post = byt_cht_es8316_resume,
  };
  
 -static const struct x86_cpu_id baytrail_cpu_ids[] = {
 -      { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */
 -      {}
 -};
 -
  static const struct acpi_gpio_params first_gpio = { 0, 0, false };
  
  static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
@@@ -479,7 -478,7 +479,7 @@@ static int snd_byt_cht_es8316_mc_probe(
        mach = dev->platform_data;
        /* fix index of codec dai */
        for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
 -              if (!strcmp(byt_cht_es8316_dais[i].codec_name,
 +              if (!strcmp(byt_cht_es8316_dais[i].codecs->name,
                            "i2c-ESSX8316:00")) {
                        dai_index = i;
                        break;
                snprintf(codec_name, sizeof(codec_name),
                         "i2c-%s", acpi_dev_name(adev));
                put_device(&adev->dev);
 -              byt_cht_es8316_dais[dai_index].codec_name = codec_name;
 +              byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
        }
  
        /* override plaform name, if required */
+       byt_cht_es8316_card.dev = dev;
        platform_name = mach->mach_params.platform;
  
        ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
        dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
        if (dmi_id) {
                quirk = (unsigned long)dmi_id->driver_data;
 -      } else if (x86_match_cpu(baytrail_cpu_ids) &&
 -          mach->mach_params.acpi_ipc_irq_index == 0) {
 +      } else if (soc_intel_is_byt() &&
 +                 mach->mach_params.acpi_ipc_irq_index == 0) {
                /* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */
                quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP |
                        BYT_CHT_ES8316_MONO_SPEAKER;
        log_quirks(dev);
  
        if (quirk & BYT_CHT_ES8316_SSP0)
 -              byt_cht_es8316_dais[dai_index].cpu_dai_name = "ssp0-port";
 +              byt_cht_es8316_dais[dai_index].cpus->dai_name = "ssp0-port";
  
        /* get the clock */
        priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
                 (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo",
                 mic_name[BYT_CHT_ES8316_MAP(quirk)]);
        byt_cht_es8316_card.long_name = long_name;
-       byt_cht_es8316_card.dev = dev;
        snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
  
        ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card);
index fb775ed7f0b8bcd1742a56e79f12635681b9193a,572e336ae0f96487e3ab43dede25c29aae6a8dff..4157c6471993d80d7f542d500a26e9cb726b788f
@@@ -337,48 -337,41 +337,48 @@@ static struct snd_soc_aux_dev cht_max98
        .codec_name = "i2c-104C227E:00",
  };
  
 +SND_SOC_DAILINK_DEF(dummy,
 +      DAILINK_COMP_ARRAY(COMP_DUMMY()));
 +
 +SND_SOC_DAILINK_DEF(media,
 +      DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(deepbuffer,
 +      DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(ssp2_port,
 +      DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 +SND_SOC_DAILINK_DEF(ssp2_codec,
 +      DAILINK_COMP_ARRAY(COMP_CODEC("i2c-193C9890:00", "HiFi")));
 +
 +SND_SOC_DAILINK_DEF(platform,
 +      DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 +
  static struct snd_soc_dai_link cht_dailink[] = {
        [MERR_DPCM_AUDIO] = {
                .name = "Audio Port",
                .stream_name = "Audio",
 -              .cpu_dai_name = "media-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(media, dummy, platform),
        },
        [MERR_DPCM_DEEP_BUFFER] = {
                .name = "Deep-Buffer Audio Port",
                .stream_name = "Deep-Buffer Audio",
 -              .cpu_dai_name = "deepbuffer-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
        },
        /* back ends */
        {
                .name = "SSP2-Codec",
                .id = 0,
 -              .cpu_dai_name = "ssp2-port",
 -              .platform_name = "sst-mfld-platform",
                .no_pcm = 1,
 -              .codec_dai_name = "HiFi",
 -              .codec_name = "i2c-193C9890:00",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                        | SND_SOC_DAIFMT_CBS_CFS,
                .init = cht_codec_init,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_be_ssp2_ops,
 +              SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
  };
  
@@@ -462,6 -454,7 +462,7 @@@ static int snd_cht_mc_probe(struct plat
        }
  
        /* override plaform name, if required */
+       snd_soc_card_cht.dev = &pdev->dev;
        mach = (&pdev->dev)->platform_data;
        platform_name = mach->mach_params.platform;
  
                return ret_val;
  
        /* register the soc card */
-       snd_soc_card_cht.dev = &pdev->dev;
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
  
        if (drv->quirks & QUIRK_PMC_PLT_CLK_0)
index 5165e5d13a8af10708cd8a4651a938f51480d3a9,20fae391c75a19e31bacc37f5a3c3818c2292be1..80b1807119176bef3c26d9cdfc8707728769e9c9
@@@ -175,59 -175,51 +175,59 @@@ static const struct snd_soc_ops cht_be_
        .hw_params = cht_aif1_hw_params,
  };
  
 +SND_SOC_DAILINK_DEF(dummy,
 +      DAILINK_COMP_ARRAY(COMP_DUMMY()));
 +
 +SND_SOC_DAILINK_DEF(media,
 +      DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(deepbuffer,
 +      DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(compress,
 +      DAILINK_COMP_ARRAY(COMP_CPU("compress-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(ssp2_port,
 +      DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 +SND_SOC_DAILINK_DEF(ssp2_codec,
 +      DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508824:00",
 +                                    NAU8824_CODEC_DAI)));
 +
 +SND_SOC_DAILINK_DEF(platform,
 +      DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 +
  static struct snd_soc_dai_link cht_dailink[] = {
        /* Front End DAI links */
        [MERR_DPCM_AUDIO] = {
                .name = "Audio Port",
                .stream_name = "Audio",
 -              .cpu_dai_name = "media-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(media, dummy, platform),
        },
        [MERR_DPCM_DEEP_BUFFER] = {
                .name = "Deep-Buffer Audio Port",
                .stream_name = "Deep-Buffer Audio",
 -              .cpu_dai_name = "deepbuffer-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
        },
        [MERR_DPCM_COMPR] = {
                .name = "Compressed Port",
                .stream_name = "Compress",
 -              .cpu_dai_name = "compress-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
 +              SND_SOC_DAILINK_REG(compress, dummy, platform),
        },
        /* Back End DAI links */
        {
                /* SSP2 - Codec */
                .name = "SSP2-Codec",
                .id = 1,
 -              .cpu_dai_name = "ssp2-port",
 -              .platform_name = "sst-mfld-platform",
                .no_pcm = 1,
 -              .codec_dai_name = NAU8824_CODEC_DAI,
 -              .codec_name = "i2c-10508824:00",
                .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
                        | SND_SOC_DAIFMT_CBS_CFS,
                .init = cht_codec_init,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_be_ssp2_ops,
 +              SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
  };
  
@@@ -266,6 -257,7 +266,7 @@@ static int snd_cht_mc_probe(struct plat
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
  
        /* override plaform name, if required */
+       snd_soc_card_cht.dev = &pdev->dev;
        mach = (&pdev->dev)->platform_data;
        platform_name = mach->mach_params.platform;
  
                return ret_val;
  
        /* register the soc card */
-       snd_soc_card_cht.dev = &pdev->dev;
        ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
        if (ret_val) {
                dev_err(&pdev->dev,
index 270d5705c5423426ec83dce1030e61d5366bb8f7,1455e19d376867f164662a0818027a2f42794a79..e03d52fe80a8fba566d3934bfa99cdc947084cb1
@@@ -295,44 -295,32 +295,44 @@@ static const struct snd_soc_ops cht_be_
        .hw_params = cht_aif1_hw_params,
  };
  
 +SND_SOC_DAILINK_DEF(dummy,
 +      DAILINK_COMP_ARRAY(COMP_DUMMY()));
 +
 +SND_SOC_DAILINK_DEF(media,
 +      DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(deepbuffer,
 +      DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 +
 +SND_SOC_DAILINK_DEF(ssp2_port,
 +      DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 +SND_SOC_DAILINK_DEF(ssp2_codec,
 +      DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5670:00",
 +                                    "rt5670-aif1")));
 +
 +SND_SOC_DAILINK_DEF(platform,
 +      DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 +
  static struct snd_soc_dai_link cht_dailink[] = {
        /* Front End DAI links */
        [MERR_DPCM_AUDIO] = {
                .name = "Audio Port",
                .stream_name = "Audio",
 -              .cpu_dai_name = "media-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(media, dummy, platform),
        },
        [MERR_DPCM_DEEP_BUFFER] = {
                .name = "Deep-Buffer Audio Port",
                .stream_name = "Deep-Buffer Audio",
 -              .cpu_dai_name = "deepbuffer-cpu-dai",
 -              .codec_dai_name = "snd-soc-dummy-dai",
 -              .codec_name = "snd-soc-dummy",
 -              .platform_name = "sst-mfld-platform",
                .nonatomic = true,
                .dynamic = 1,
                .dpcm_playback = 1,
                .ops = &cht_aif1_ops,
 +              SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
        },
  
        /* Back End DAI links */
                /* SSP2 - Codec */
                .name = "SSP2-Codec",
                .id = 0,
 -              .cpu_dai_name = "ssp2-port",
 -              .platform_name = "sst-mfld-platform",
                .no_pcm = 1,
                .nonatomic = true,
 -              .codec_dai_name = "rt5670-aif1",
 -              .codec_name = "i2c-10EC5670:00",
                .init = cht_codec_init,
                .be_hw_params_fixup = cht_codec_fixup,
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .ops = &cht_be_ssp2_ops,
 +              SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
  };
  
@@@ -426,15 -417,16 +426,16 @@@ static int snd_cht_mc_probe(struct plat
                         "i2c-%s", acpi_dev_name(adev));
                put_device(&adev->dev);
                for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
 -                      if (!strcmp(cht_dailink[i].codec_name,
 -                              RT5672_I2C_DEFAULT)) {
 -                              cht_dailink[i].codec_name = drv->codec_name;
 +                      if (!strcmp(cht_dailink[i].codecs->name,
 +                                  RT5672_I2C_DEFAULT)) {
 +                              cht_dailink[i].codecs->name = drv->codec_name;
                                break;
                        }
                }
        }
  
        /* override plaform name, if required */
+       snd_soc_card_cht.dev = &pdev->dev;
        platform_name = mach->mach_params.platform;
  
        ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
  
        /* register the soc card */
-       snd_soc_card_cht.dev = &pdev->dev;
        ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
        if (ret_val) {
                dev_err(&pdev->dev,
diff --combined sound/soc/soc-core.c
index f8426c8120b2b1301029a55f4cd250381cfe209a,3fecd957995e0deea5c3d71431e89fa207ad70e0..94a36ee8eb224606be62e248f105fbaa18f965bd
@@@ -57,13 -57,6 +57,13 @@@ static LIST_HEAD(unbind_card_list)
  #define for_each_component(component)                 \
        list_for_each_entry(component, &component_list, list)
  
 +/*
 + * This is used if driver don't need to have CPU/Codec/Platform
 + * dai_link. see soc.h
 + */
 +struct snd_soc_dai_link_component null_dailink_component[0];
 +EXPORT_SYMBOL_GPL(null_dailink_component);
 +
  /*
   * This is a timeout to do a DAPM powerdown after a stream is closed().
   * It can be used to eliminate pops between different playback streams, e.g.
@@@ -697,8 -690,6 +697,8 @@@ int snd_soc_resume(struct device *dev
        struct snd_soc_card *card = dev_get_drvdata(dev);
        bool bus_control = false;
        struct snd_soc_pcm_runtime *rtd;
 +      struct snd_soc_dai *codec_dai;
 +      int i;
  
        /* If the card is not initialized yet there is nothing to do */
        if (!card->instantiated)
  
        /* activate pins from sleep state */
        for_each_card_rtds(card, rtd) {
 -              struct snd_soc_dai *codec_dai;
                struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 -              int j;
  
                if (cpu_dai->active)
                        pinctrl_pm_select_default_state(cpu_dai->dev);
  
 -              for_each_rtd_codec_dai(rtd, j, codec_dai) {
 +              for_each_rtd_codec_dai(rtd, i, codec_dai) {
                        if (codec_dai->active)
                                pinctrl_pm_select_default_state(codec_dai->dev);
                }
@@@ -748,18 -741,6 +748,18 @@@ EXPORT_SYMBOL_GPL(snd_soc_resume)
  static const struct snd_soc_dai_ops null_dai_ops = {
  };
  
 +static struct device_node
 +*soc_component_to_node(struct snd_soc_component *component)
 +{
 +      struct device_node *of_node;
 +
 +      of_node = component->dev->of_node;
 +      if (!of_node && component->dev->parent)
 +              of_node = component->dev->parent->of_node;
 +
 +      return of_node;
 +}
 +
  static struct snd_soc_component *soc_find_component(
        const struct device_node *of_node, const char *name)
  {
  
        for_each_component(component) {
                if (of_node) {
 -                      component_of_node = component->dev->of_node;
 -                      if (!component_of_node && component->dev->parent)
 -                              component_of_node = component->dev->parent->of_node;
 +                      component_of_node = soc_component_to_node(component);
  
                        if (component_of_node == of_node)
                                return component;
@@@ -788,7 -771,9 +788,7 @@@ static int snd_soc_is_matching_componen
  {
        struct device_node *component_of_node;
  
 -      component_of_node = component->dev->of_node;
 -      if (!component_of_node && component->dev->parent)
 -              component_of_node = component->dev->parent->of_node;
 +      component_of_node = soc_component_to_node(component);
  
        if (dlc->of_node && component_of_node != dlc->of_node)
                return 0;
@@@ -894,7 -879,9 +894,7 @@@ static int soc_bind_dai_link(struct snd
  {
        struct snd_soc_pcm_runtime *rtd;
        struct snd_soc_dai_link_component *codecs;
 -      struct snd_soc_dai_link_component cpu_dai_component;
        struct snd_soc_component *component;
 -      struct snd_soc_dai **codec_dais;
        int i;
  
        if (dai_link->ignore)
        if (!rtd)
                return -ENOMEM;
  
 -      cpu_dai_component.name = dai_link->cpu_name;
 -      cpu_dai_component.of_node = dai_link->cpu_of_node;
 -      cpu_dai_component.dai_name = dai_link->cpu_dai_name;
 -      rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component);
 +      /* FIXME: we need multi CPU support in the future */
 +      rtd->cpu_dai = snd_soc_find_dai(dai_link->cpus);
        if (!rtd->cpu_dai) {
                dev_info(card->dev, "ASoC: CPU DAI %s not registered\n",
 -                       dai_link->cpu_dai_name);
 +                       dai_link->cpus->dai_name);
                goto _err_defer;
        }
        snd_soc_rtdcom_add(rtd, rtd->cpu_dai->component);
  
 -      rtd->num_codecs = dai_link->num_codecs;
 -
        /* Find CODEC from registered CODECs */
 -      codec_dais = rtd->codec_dais;
 +      rtd->num_codecs = dai_link->num_codecs;
        for_each_link_codecs(dai_link, i, codecs) {
 -              codec_dais[i] = snd_soc_find_dai(codecs);
 -              if (!codec_dais[i]) {
 +              rtd->codec_dais[i] = snd_soc_find_dai(codecs);
 +              if (!rtd->codec_dais[i]) {
                        dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n",
                                 codecs->dai_name);
                        goto _err_defer;
                }
 -              snd_soc_rtdcom_add(rtd, codec_dais[i]->component);
 +              snd_soc_rtdcom_add(rtd, rtd->codec_dais[i]->component);
        }
  
        /* Single codec links expect codec and codec_dai in runtime data */
 -      rtd->codec_dai = codec_dais[0];
 +      rtd->codec_dai = rtd->codec_dais[0];
  
 -      /* find one from the set of registered platforms */
 +      /* Find PLATFORM from registered PLATFORMs */
        for_each_component(component) {
                if (!snd_soc_is_matching_component(dai_link->platforms,
                                                   component))
@@@ -955,7 -946,6 +955,7 @@@ _err_defer
  
  static void soc_cleanup_component(struct snd_soc_component *component)
  {
 +      snd_soc_component_set_jack(component, NULL, NULL);
        list_del(&component->card_list);
        snd_soc_dapm_free(snd_soc_component_get_dapm(component));
        soc_cleanup_component_debugfs(component);
@@@ -1053,18 -1043,117 +1053,18 @@@ static void soc_remove_dai_links(struc
        }
  }
  
 -static int snd_soc_init_platform(struct snd_soc_card *card,
 -                               struct snd_soc_dai_link *dai_link)
 -{
 -      struct snd_soc_dai_link_component *platform = dai_link->platforms;
 -
 -      /*
 -       * REMOVE ME
 -       *
 -       * This is glue code for Legacy vs Modern dai_link.
 -       * This function will be removed if all derivers are switched to
 -       * modern style dai_link.
 -       * Driver shouldn't use both legacy and modern style in the same time.
 -       * see
 -       *      soc.h :: struct snd_soc_dai_link
 -       */
 -      /* convert Legacy platform link */
 -      if (!platform) {
 -              platform = devm_kzalloc(card->dev,
 -                              sizeof(struct snd_soc_dai_link_component),
 -                              GFP_KERNEL);
 -              if (!platform)
 -                      return -ENOMEM;
 -
 -              dai_link->platforms       = platform;
 -              dai_link->num_platforms   = 1;
 -              dai_link->legacy_platform = 1;
 -              platform->name            = dai_link->platform_name;
 -              platform->of_node         = dai_link->platform_of_node;
 -              platform->dai_name        = NULL;
 -      }
 -
 -      /* if there's no platform we match on the empty platform */
 -      if (!platform->name &&
 -          !platform->of_node)
 -              platform->name = "snd-soc-dummy";
 -
 -      return 0;
 -}
 -
 -static void soc_cleanup_platform(struct snd_soc_card *card)
 -{
 -      struct snd_soc_dai_link *link;
 -      int i;
 -      /*
 -       * FIXME
 -       *
 -       * this function should be removed with snd_soc_init_platform
 -       */
 -
 -      for_each_card_prelinks(card, i, link) {
 -              if (link->legacy_platform) {
 -                      link->legacy_platform = 0;
 -                      link->platforms       = NULL;
 -              }
 -      }
 -}
 -
 -static int snd_soc_init_multicodec(struct snd_soc_card *card,
 -                                 struct snd_soc_dai_link *dai_link)
 -{
 -      /*
 -       * REMOVE ME
 -       *
 -       * This is glue code for Legacy vs Modern dai_link.
 -       * This function will be removed if all derivers are switched to
 -       * modern style dai_link.
 -       * Driver shouldn't use both legacy and modern style in the same time.
 -       * see
 -       *      soc.h :: struct snd_soc_dai_link
 -       */
 -
 -      /* Legacy codec/codec_dai link is a single entry in multicodec */
 -      if (dai_link->codec_name || dai_link->codec_of_node ||
 -          dai_link->codec_dai_name) {
 -              dai_link->num_codecs = 1;
 -
 -              dai_link->codecs = devm_kzalloc(card->dev,
 -                              sizeof(struct snd_soc_dai_link_component),
 -                              GFP_KERNEL);
 -              if (!dai_link->codecs)
 -                      return -ENOMEM;
 -
 -              dai_link->codecs[0].name = dai_link->codec_name;
 -              dai_link->codecs[0].of_node = dai_link->codec_of_node;
 -              dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
 -      }
 -
 -      if (!dai_link->codecs) {
 -              dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
 -              return -EINVAL;
 -      }
 -
 -      return 0;
 -}
 +static struct snd_soc_dai_link_component dummy_link = COMP_DUMMY();
  
  static int soc_init_dai_link(struct snd_soc_card *card,
                             struct snd_soc_dai_link *link)
  {
 -      int i, ret;
 +      int i;
        struct snd_soc_dai_link_component *codec;
  
 -      ret = snd_soc_init_platform(card, link);
 -      if (ret) {
 -              dev_err(card->dev, "ASoC: failed to init multiplatform\n");
 -              return ret;
 -      }
 -
 -      ret = snd_soc_init_multicodec(card, link);
 -      if (ret) {
 -              dev_err(card->dev, "ASoC: failed to init multicodec\n");
 -              return ret;
 +      /* default Platform */
 +      if (!link->platforms || !link->num_platforms) {
 +              link->platforms = &dummy_link;
 +              link->num_platforms = 1;
        }
  
        for_each_link_codecs(link, i, codec) {
            !soc_find_component(link->platforms->of_node, link->platforms->name))
                return -EPROBE_DEFER;
  
 +      /* FIXME */
 +      if (link->num_cpus > 1) {
 +              dev_err(card->dev,
 +                      "ASoC: multi cpu is not yet supported %s\n",
 +                      link->name);
 +              return -EINVAL;
 +      }
 +
        /*
         * CPU device may be specified by either name or OF node, but
         * can be left unspecified, and will be matched based on DAI
         * name alone..
         */
 -      if (link->cpu_name && link->cpu_of_node) {
 +      if (link->cpus->name && link->cpus->of_node) {
                dev_err(card->dev,
                        "ASoC: Neither/both cpu name/of_node are set for %s\n",
                        link->name);
         * Defer card registartion if cpu dai component is not added to
         * component list.
         */
 -      if ((link->cpu_of_node || link->cpu_name) &&
 -          !soc_find_component(link->cpu_of_node, link->cpu_name))
 +      if ((link->cpus->of_node || link->cpus->name) &&
 +          !soc_find_component(link->cpus->of_node, link->cpus->name))
                return -EPROBE_DEFER;
  
        /*
         * At least one of CPU DAI name or CPU device name/node must be
         * specified
         */
 -      if (!link->cpu_dai_name &&
 -          !(link->cpu_name || link->cpu_of_node)) {
 +      if (!link->cpus->dai_name &&
 +          !(link->cpus->name || link->cpus->of_node)) {
                dev_err(card->dev,
                        "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
                        link->name);
@@@ -1244,10 -1325,13 +1244,10 @@@ EXPORT_SYMBOL_GPL(snd_soc_remove_dai_li
  
  static void soc_set_of_name_prefix(struct snd_soc_component *component)
  {
 -      struct device_node *component_of_node = component->dev->of_node;
 +      struct device_node *component_of_node = soc_component_to_node(component);
        const char *str;
        int ret;
  
 -      if (!component_of_node && component->dev->parent)
 -              component_of_node = component->dev->parent->of_node;
 -
        ret = of_property_read_string(component_of_node, "sound-name-prefix",
                                      &str);
        if (!ret)
@@@ -1261,7 -1345,10 +1261,7 @@@ static void soc_set_name_prefix(struct 
  
        for (i = 0; i < card->num_configs && card->codec_conf; i++) {
                struct snd_soc_codec_conf *map = &card->codec_conf[i];
 -              struct device_node *component_of_node = component->dev->of_node;
 -
 -              if (!component_of_node && component->dev->parent)
 -                      component_of_node = component->dev->parent->of_node;
 +              struct device_node *component_of_node = soc_component_to_node(component);
  
                if (map->of_node && component_of_node != map->of_node)
                        continue;
@@@ -1339,11 -1426,12 +1339,11 @@@ static int soc_probe_component(struct s
                                "ASoC: failed to probe component %d\n", ret);
                        goto err_probe;
                }
 -
 -              WARN(dapm->idle_bias_off &&
 -                      dapm->bias_level != SND_SOC_BIAS_OFF,
 -                      "codec %s can not start from non-off bias with idle_bias_off==1\n",
 -                      component->name);
        }
 +      WARN(dapm->idle_bias_off &&
 +           dapm->bias_level != SND_SOC_BIAS_OFF,
 +           "codec %s can not start from non-off bias with idle_bias_off==1\n",
 +           component->name);
  
        /* machine specific init */
        if (component->init) {
@@@ -1911,7 -1999,7 +1911,7 @@@ match
                                 card->dai_link[i].name);
  
                        /* override platform component */
 -                      if (snd_soc_init_platform(card, dai_link) < 0) {
 +                      if (!dai_link->platforms) {
                                dev_err(card->dev, "init platform error");
                                continue;
                        }
@@@ -1962,6 -2050,7 +1962,6 @@@ static int soc_cleanup_card_resources(s
        /* remove and free each DAI */
        soc_remove_dai_links(card);
        soc_remove_pcm_runtimes(card);
 -      soc_cleanup_platform(card);
  
        /* remove auxiliary devices */
        soc_remove_aux_devices(card);
@@@ -1983,6 -2072,16 +1983,16 @@@ static int snd_soc_instantiate_card(str
        int ret, i, order;
  
        mutex_lock(&client_mutex);
 -                      soc_cleanup_platform(card);
+       for_each_card_prelinks(card, i, dai_link) {
+               ret = soc_init_dai_link(card, dai_link);
+               if (ret) {
++                      soc_cleanup_card_resources(card);
+                       dev_err(card->dev, "ASoC: failed to init link %s: %d\n",
+                               dai_link->name, ret);
+                       mutex_unlock(&client_mutex);
+                       return ret;
+               }
+       }
        mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
  
        card->dapm.bias_level = SND_SOC_BIAS_OFF;
@@@ -2707,25 -2806,9 +2717,9 @@@ static int snd_soc_bind_card(struct snd
   */
  int snd_soc_register_card(struct snd_soc_card *card)
  {
-       int i, ret;
-       struct snd_soc_dai_link *link;
        if (!card->name || !card->dev)
                return -EINVAL;
  
-       mutex_lock(&client_mutex);
-       for_each_card_prelinks(card, i, link) {
-               ret = soc_init_dai_link(card, link);
-               if (ret) {
-                       dev_err(card->dev, "ASoC: failed to init link %s\n",
-                               link->name);
-                       mutex_unlock(&client_mutex);
-                       return ret;
-               }
-       }
-       mutex_unlock(&client_mutex);
        dev_set_drvdata(card->dev, card);
  
        snd_soc_initialize_card_lists(card);
@@@ -3669,7 -3752,7 +3663,7 @@@ EXPORT_SYMBOL_GPL(snd_soc_of_parse_daif
  
  int snd_soc_get_dai_id(struct device_node *ep)
  {
 -      struct snd_soc_component *pos;
 +      struct snd_soc_component *component;
        struct device_node *node;
        int ret;
  
         */
        ret = -ENOTSUPP;
        mutex_lock(&client_mutex);
 -      for_each_component(pos) {
 -              struct device_node *component_of_node = pos->dev->of_node;
 -
 -              if (!component_of_node && pos->dev->parent)
 -                      component_of_node = pos->dev->parent->of_node;
 -
 -              if (component_of_node != node)
 -                      continue;
 -
 -              if (pos->driver->of_xlate_dai_id)
 -                      ret = pos->driver->of_xlate_dai_id(pos, ep);
 -
 -              break;
 -      }
 +      component = soc_find_component(node, NULL);
 +      if (component &&
 +          component->driver->of_xlate_dai_id)
 +              ret = component->driver->of_xlate_dai_id(component, ep);
        mutex_unlock(&client_mutex);
  
        of_node_put(node);
@@@ -3704,7 -3797,9 +3698,7 @@@ int snd_soc_get_dai_name(struct of_phan
  
        mutex_lock(&client_mutex);
        for_each_component(pos) {
 -              component_of_node = pos->dev->of_node;
 -              if (!component_of_node && pos->dev->parent)
 -                      component_of_node = pos->dev->parent->of_node;
 +              component_of_node = soc_component_to_node(pos);
  
                if (component_of_node != args->np)
                        continue;
index bb5f02f4e49a064cc4103329cb8fa0b16d5aba45,faf1a8ada091fddc7352a9b7ac107ab7a80a8c9d..47b508463218a9eebd9b92292f1598a79c24a548
@@@ -227,7 -227,9 +227,9 @@@ static int hda_init(struct snd_sof_dev 
  
        /* initialise hdac bus */
        bus->addr = pci_resource_start(pci, 0);
+ #if IS_ENABLED(CONFIG_PCI)
        bus->remap_addr = pci_ioremap_bar(pci, 0);
+ #endif
        if (!bus->remap_addr) {
                dev_err(bus->dev, "error: ioremap error\n");
                return -ENXIO;
@@@ -454,7 -456,9 +456,9 @@@ int hda_dsp_probe(struct snd_sof_dev *s
                goto hdac_bus_unmap;
  
        /* DSP base */
+ #if IS_ENABLED(CONFIG_PCI)
        sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR);
+ #endif
        if (!sdev->bar[HDA_DSP_BAR]) {
                dev_err(sdev->dev, "error: ioremap error\n");
                ret = -ENXIO;
         * TODO: support interrupt mode selection with kernel parameter
         *       support msi multiple vectors
         */
 +#if IS_ENABLED(CONFIG_PCI)
        ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI);
 +#endif
        if (ret < 0) {
                dev_info(sdev->dev, "use legacy interrupt mode\n");
                /*
                sdev->msi_enabled = 0;
        } else {
                dev_info(sdev->dev, "use msi interrupt mode\n");
 +#if IS_ENABLED(CONFIG_PCI)
                hdev->irq = pci_irq_vector(pci, 0);
 +#endif
                /* ipc irq number is the same of hda irq */
                sdev->ipc_irq = hdev->irq;
                sdev->msi_enabled = 1;
@@@ -565,10 -565,8 +569,10 @@@ free_ipc_irq
  free_hda_irq:
        free_irq(hdev->irq, bus);
  free_irq_vector:
 +#if IS_ENABLED(CONFIG_PCI)
        if (sdev->msi_enabled)
                pci_free_irq_vectors(pci);
 +#endif
  free_streams:
        hda_dsp_stream_free(sdev);
  /* dsp_unmap: not currently used */
@@@ -583,6 -581,7 +587,6 @@@ int hda_dsp_remove(struct snd_sof_dev *
  {
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        struct hdac_bus *bus = sof_to_bus(sdev);
 -      struct pci_dev *pci = to_pci_dev(sdev->dev);
        const struct sof_intel_dsp_desc *chip = hda->desc;
  
  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
  
        free_irq(sdev->ipc_irq, sdev);
        free_irq(hda->irq, bus);
 -      if (sdev->msi_enabled)
 +#if IS_ENABLED(CONFIG_PCI)
 +      if (sdev->msi_enabled) {
 +              struct pci_dev *pci = to_pci_dev(sdev->dev);
                pci_free_irq_vectors(pci);
 +      }
 +#endif
  
        hda_dsp_stream_free(sdev);
  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
index 03696f880080f5e65c7dc41a16d671c172cb53bc,bc128e2a609680d677c4459295535dafee165c3a..f3ff5a0b5666c316e94b1bfb465c81dc00b60f44
  
  #define SUN8I_I2S_TX_CHAN_MAP_REG     0x44
  #define SUN8I_I2S_TX_CHAN_SEL_REG     0x34
- #define SUN8I_I2S_TX_CHAN_OFFSET_MASK         GENMASK(13, 11)
+ #define SUN8I_I2S_TX_CHAN_OFFSET_MASK         GENMASK(13, 12)
  #define SUN8I_I2S_TX_CHAN_OFFSET(offset)      (offset << 12)
  #define SUN8I_I2S_TX_CHAN_EN_MASK             GENMASK(11, 4)
  #define SUN8I_I2S_TX_CHAN_EN(num_chan)                (((1 << num_chan) - 1) << 4)
  #define SUN8I_I2S_RX_CHAN_SEL_REG     0x54
  #define SUN8I_I2S_RX_CHAN_MAP_REG     0x58
  
 +struct sun4i_i2s;
 +
  /**
   * struct sun4i_i2s_quirks - Differences between SoC variants.
   *
   * @sun4i_i2s_regmap: regmap config to use.
   * @mclk_offset: Value by which mclkdiv needs to be adjusted.
   * @bclk_offset: Value by which bclkdiv needs to be adjusted.
 - * @fmt_offset: Value by which wss and sr needs to be adjusted.
   * @field_clkdiv_mclk_en: regmap field to enable mclk output.
   * @field_fmt_wss: regmap field to set word select size.
   * @field_fmt_sr: regmap field to set sample resolution.
@@@ -155,6 -154,7 +155,6 @@@ struct sun4i_i2s_quirks 
        const struct regmap_config      *sun4i_i2s_regmap;
        unsigned int                    mclk_offset;
        unsigned int                    bclk_offset;
 -      unsigned int                    fmt_offset;
  
        /* Register fields for i2s */
        struct reg_field                field_clkdiv_mclk_en;
        struct reg_field                field_rxchanmap;
        struct reg_field                field_txchansel;
        struct reg_field                field_rxchansel;
 +
 +      s8      (*get_sr)(const struct sun4i_i2s *, int);
 +      s8      (*get_wss)(const struct sun4i_i2s *, int);
  };
  
  struct sun4i_i2s {
@@@ -352,39 -349,6 +352,39 @@@ static int sun4i_i2s_set_clk_rate(struc
        return 0;
  }
  
 +static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width)
 +{
 +      if (width < 16 || width > 24)
 +              return -EINVAL;
 +
 +      if (width % 4)
 +              return -EINVAL;
 +
 +      return (width - 16) / 4;
 +}
 +
 +static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width)
 +{
 +      if (width < 16 || width > 32)
 +              return -EINVAL;
 +
 +      if (width % 4)
 +              return -EINVAL;
 +
 +      return (width - 16) / 4;
 +}
 +
 +static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
 +{
 +      if (width % 4)
 +              return -EINVAL;
 +
 +      if (width < 8 || width > 32)
 +              return -EINVAL;
 +
 +      return (width - 8) / 4 + 1;
 +}
 +
  static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *params,
                               struct snd_soc_dai *dai)
        }
        i2s->playback_dma_data.addr_width = width;
  
 -      switch (params_width(params)) {
 -      case 16:
 -              sr = 0;
 -              wss = 0;
 -              break;
 +      sr = i2s->variant->get_sr(i2s, params_width(params));
 +      if (sr < 0)
 +              return -EINVAL;
  
 -      default:
 -              dev_err(dai->dev, "Unsupported sample width: %d\n",
 -                      params_width(params));
 +      wss = i2s->variant->get_wss(i2s, params_width(params));
 +      if (wss < 0)
                return -EINVAL;
 -      }
  
 -      regmap_field_write(i2s->field_fmt_wss,
 -                         wss + i2s->variant->fmt_offset);
 -      regmap_field_write(i2s->field_fmt_sr,
 -                         sr + i2s->variant->fmt_offset);
 +      regmap_field_write(i2s->field_fmt_wss, wss);
 +      regmap_field_write(i2s->field_fmt_sr, sr);
  
        return sun4i_i2s_set_clk_rate(dai, params_rate(params),
                                      params_width(params));
@@@ -490,6 -460,10 +490,10 @@@ static int sun4i_i2s_set_fmt(struct snd
                regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
                                   SUN8I_I2S_TX_CHAN_OFFSET_MASK,
                                   SUN8I_I2S_TX_CHAN_OFFSET(offset));
+               regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
+                                  SUN8I_I2S_TX_CHAN_OFFSET_MASK,
+                                  SUN8I_I2S_TX_CHAN_OFFSET(offset));
        }
  
        regmap_field_write(i2s->field_fmt_mode, val);
@@@ -921,8 -895,6 +925,8 @@@ static const struct sun4i_i2s_quirks su
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
 +      .get_sr                 = sun4i_i2s_get_sr,
 +      .get_wss                = sun4i_i2s_get_wss,
  };
  
  static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
 +      .get_sr                 = sun4i_i2s_get_sr,
 +      .get_wss                = sun4i_i2s_get_wss,
  };
  
  static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
 +      .get_sr                 = sun8i_i2s_get_sr_wss,
 +      .get_wss                = sun8i_i2s_get_sr_wss,
  };
  
  static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
        .sun4i_i2s_regmap       = &sun8i_i2s_regmap_config,
        .mclk_offset            = 1,
        .bclk_offset            = 2,
 -      .fmt_offset             = 3,
        .has_fmt_set_lrck_period = true,
        .has_chcfg              = true,
        .has_chsel_tx_chen      = true,
        .field_rxchanmap        = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2),
 +      .get_sr                 = sun8i_i2s_get_sr_wss,
 +      .get_wss                = sun8i_i2s_get_sr_wss,
  };
  
  static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
 +      .get_sr                 = sun8i_i2s_get_sr_wss,
 +      .get_wss                = sun8i_i2s_get_sr_wss,
  };
  
  static int sun4i_i2s_init_regmap_fields(struct device *dev,