Merge branch 'asoc-5.4' into asoc-next
authorMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:44 +0000 (10:31 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:44 +0000 (10:31 +0100)
17 files changed:
1  2 
include/sound/soc-dapm.h
include/sound/sof/dai-intel.h
include/sound/sof/dai.h
sound/core/pcm_native.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_intel.c
sound/soc/atmel/mchp-i2s-mcc.c
sound/soc/codecs/es8316.c
sound/soc/codecs/rt1011.c
sound/soc/fsl/fsl_ssi.c
sound/soc/intel/common/sst-ipc.c
sound/soc/intel/skylake/skl-debug.c
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/soc-topology.c
sound/soc/ti/davinci-i2s.c

diff --combined include/sound/soc-dapm.h
@@@ -353,6 -353,8 +353,8 @@@ struct device
  #define SND_SOC_DAPM_WILL_PMD   0x80    /* called at start of sequence */
  #define SND_SOC_DAPM_PRE_POST_PMD \
                                (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
+ #define SND_SOC_DAPM_PRE_POST_PMU \
+                               (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU)
  
  /* convenience event type detection */
  #define SND_SOC_DAPM_EVENT_ON(e)      \
@@@ -402,9 -404,6 +404,9 @@@ int snd_soc_dapm_new_controls(struct sn
  struct snd_soc_dapm_widget *snd_soc_dapm_new_control(
                struct snd_soc_dapm_context *dapm,
                const struct snd_soc_dapm_widget *widget);
 +struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked(
 +              struct snd_soc_dapm_context *dapm,
 +              const struct snd_soc_dapm_widget *widget);
  int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
                                 struct snd_soc_dai *dai);
  int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
@@@ -417,6 -416,9 +419,9 @@@ int snd_soc_dapm_update_dai(struct snd_
  /* dapm path setup */
  int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
  void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
+ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm,
+                      struct snd_soc_card *card,
+                      struct snd_soc_component *component);
  int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
                            const struct snd_soc_dapm_route *route, int num);
  int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
@@@ -662,8 -664,6 +667,6 @@@ struct snd_soc_dapm_context 
        unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
        /* Go to BIAS_OFF in suspend if the DAPM context is idle */
        unsigned int suspend_bias_off:1;
-       void (*seq_notifier)(struct snd_soc_dapm_context *,
-                            enum snd_soc_dapm_type, int);
  
        struct device *dev; /* from parent - for debug */
        struct snd_soc_component *component; /* parent component */
        enum snd_soc_bias_level target_bias_level;
        struct list_head list;
  
-       int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
-       int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
-                             enum snd_soc_bias_level level);
        struct snd_soc_dapm_wcache path_sink_cache;
        struct snd_soc_dapm_wcache path_source_cache;
  
@@@ -1,4 -1,4 +1,4 @@@
 -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
  /*
   * This file is provided under a dual BSD/GPLv2 license.  When using or
   * redistributing this file, you may do so under either license.
@@@ -76,6 -76,9 +76,9 @@@ struct sof_ipc_dai_ssp_params 
        uint16_t tdm_per_slot_padding_flag;
        uint32_t clks_control;
        uint32_t quirks;
+       uint32_t bclk_delay;    /* guaranteed time (ms) for which BCLK
+                                * will be driven, before sending data
+                                */
  } __packed;
  
  /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */
@@@ -176,4 -179,13 +179,13 @@@ struct sof_ipc_dai_dmic_params 
        struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
  } __packed;
  
+ /* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
+ struct sof_ipc_dai_alh_params {
+       struct sof_ipc_hdr hdr;
+       uint32_t stream_id;
+       /* reserved for future use */
+       uint32_t reserved[15];
+ } __packed;
  #endif
diff --combined include/sound/sof/dai.h
@@@ -1,4 -1,4 +1,4 @@@
 -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
  /*
   * This file is provided under a dual BSD/GPLv2 license.  When using or
   * redistributing this file, you may do so under either license.
@@@ -49,7 -49,9 +49,9 @@@ enum sof_ipc_dai_type 
        SOF_DAI_INTEL_SSP,              /**< Intel SSP */
        SOF_DAI_INTEL_DMIC,             /**< Intel DMIC */
        SOF_DAI_INTEL_HDA,              /**< Intel HD/A */
-       SOF_DAI_INTEL_SOUNDWIRE,        /**< Intel SoundWire */
+       SOF_DAI_INTEL_ALH,              /**< Intel ALH  */
+       SOF_DAI_IMX_SAI,                /**< i.MX SAI */
+       SOF_DAI_IMX_ESAI,               /**< i.MX ESAI */
  };
  
  /* general purpose DAI configuration */
@@@ -70,6 -72,7 +72,7 @@@ struct sof_ipc_dai_config 
                struct sof_ipc_dai_ssp_params ssp;
                struct sof_ipc_dai_dmic_params dmic;
                struct sof_ipc_dai_hda_params hda;
+               struct sof_ipc_dai_alh_params alh;
        };
  } __packed;
  
diff --combined sound/core/pcm_native.c
@@@ -77,7 -77,7 +77,7 @@@ void snd_pcm_group_init(struct snd_pcm_
        spin_lock_init(&group->lock);
        mutex_init(&group->mutex);
        INIT_LIST_HEAD(&group->substreams);
 -      refcount_set(&group->refs, 0);
 +      refcount_set(&group->refs, 1);
  }
  
  /* define group lock helpers */
@@@ -1096,7 -1096,8 +1096,7 @@@ static void snd_pcm_group_unref(struct 
  
        if (!group)
                return;
 -      do_free = refcount_dec_and_test(&group->refs) &&
 -              list_empty(&group->substreams);
 +      do_free = refcount_dec_and_test(&group->refs);
        snd_pcm_group_unlock(group, substream->pcm->nonatomic);
        if (do_free)
                kfree(group);
@@@ -1873,7 -1874,6 +1873,7 @@@ static int snd_pcm_drain(struct snd_pcm
                if (!to_check)
                        break; /* all drained */
                init_waitqueue_entry(&wait, current);
 +              set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&to_check->sleep, &wait);
                snd_pcm_stream_unlock_irq(substream);
                if (runtime->no_period_wakeup)
                        }
                        tout = msecs_to_jiffies(tout * 1000);
                }
 -              tout = schedule_timeout_interruptible(tout);
 +              tout = schedule_timeout(tout);
  
                snd_pcm_stream_lock_irq(substream);
                group = snd_pcm_stream_group_ref(substream);
@@@ -2020,7 -2020,6 +2020,7 @@@ static int snd_pcm_link(struct snd_pcm_
        snd_pcm_group_lock_irq(target_group, nonatomic);
        snd_pcm_stream_lock(substream1);
        snd_pcm_group_assign(substream1, target_group);
 +      refcount_inc(&target_group->refs);
        snd_pcm_stream_unlock(substream1);
        snd_pcm_group_unlock_irq(target_group, nonatomic);
   _end:
@@@ -2057,14 -2056,13 +2057,14 @@@ static int snd_pcm_unlink(struct snd_pc
        snd_pcm_group_lock_irq(group, nonatomic);
  
        relink_to_local(substream);
 +      refcount_dec(&group->refs);
  
        /* detach the last stream, too */
        if (list_is_singular(&group->substreams)) {
                relink_to_local(list_first_entry(&group->substreams,
                                                 struct snd_pcm_substream,
                                                 link_list));
 -              do_free = !refcount_read(&group->refs);
 +              do_free = refcount_dec_and_test(&group->refs);
        }
  
        snd_pcm_group_unlock_irq(group, nonatomic);
@@@ -2170,7 -2168,7 +2170,7 @@@ static int snd_pcm_hw_rule_sample_bits(
  
  static const unsigned int rates[] = {
        5512, 8000, 11025, 16000, 22050, 32000, 44100,
-       48000, 64000, 88200, 96000, 176400, 192000
+       48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000
  };
  
  const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
@@@ -846,7 -846,13 +846,13 @@@ static void snd_hda_codec_dev_release(s
        snd_hda_sysfs_clear(codec);
        kfree(codec->modelname);
        kfree(codec->wcaps);
-       kfree(codec);
+       /*
+        * In the case of ASoC HD-audio, hda_codec is device managed.
+        * It will be freed when the ASoC device is removed.
+        */
+       if (codec->core.type == HDA_DEV_LEGACY)
+               kfree(codec);
  }
  
  #define DEV_NAME_LEN 31
@@@ -2942,7 -2948,7 +2948,7 @@@ static int hda_codec_runtime_resume(str
  static int hda_codec_force_resume(struct device *dev)
  {
        struct hda_codec *codec = dev_to_hda_codec(dev);
 -      bool forced_resume = !codec->relaxed_resume;
 +      bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used;
        int ret;
  
        /* The get/put pair below enforces the runtime resume even if the
@@@ -598,9 -598,11 +598,9 @@@ static int azx_pcm_open(struct snd_pcm_
        }
        runtime->private_data = azx_dev;
  
 -      if (chip->gts_present)
 -              azx_pcm_hw.info = azx_pcm_hw.info |
 -                      SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
 -
        runtime->hw = azx_pcm_hw;
 +      if (chip->gts_present)
 +              runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
        runtime->hw.channels_min = hinfo->channels_min;
        runtime->hw.channels_max = hinfo->channels_max;
        runtime->hw.formats = hinfo->formats;
                                     20,
                                     178000000);
  
 +      /* by some reason, the playback stream stalls on PulseAudio with
 +       * tsched=1 when a capture stream triggers.  Until we figure out the
 +       * real cause, disable tsched mode by telling the PCM info flag.
 +       */
 +      if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND)
 +              runtime->hw.info |= SNDRV_PCM_INFO_BATCH;
 +
        if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
@@@ -1207,14 -1202,12 +1207,12 @@@ void snd_hda_bus_reset(struct hda_bus *
  }
  
  /* HD-audio bus initialization */
- int azx_bus_init(struct azx *chip, const char *model,
-                const struct hdac_io_ops *io_ops)
+ int azx_bus_init(struct azx *chip, const char *model)
  {
        struct hda_bus *bus = &chip->bus;
        int err;
  
-       err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops,
-                               io_ops);
+       err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops);
        if (err < 0)
                return err;
  
@@@ -31,7 -31,7 +31,7 @@@
  /* 14 unused */
  #define AZX_DCAPS_CTX_WORKAROUND (1 << 15)    /* X-Fi workaround */
  #define AZX_DCAPS_POSFIX_LPIB (1 << 16)       /* Use LPIB as default */
 -/* 17 unused */
 +#define AZX_DCAPS_AMD_WORKAROUND (1 << 17)    /* AMD-specific workaround */
  #define AZX_DCAPS_NO_64BIT    (1 << 18)       /* No 64bit address */
  #define AZX_DCAPS_SYNC_WRITE  (1 << 19)       /* sync each cmd write */
  #define AZX_DCAPS_OLD_SSYNC   (1 << 20)       /* Old SSYNC reg for ICH */
@@@ -206,8 -206,7 +206,7 @@@ void azx_stop_chip(struct azx *chip)
  irqreturn_t azx_interrupt(int irq, void *dev_id);
  
  /* Codec interface */
- int azx_bus_init(struct azx *chip, const char *model,
-                const struct hdac_io_ops *io_ops);
+ int azx_bus_init(struct azx *chip, const char *model);
  int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
  int azx_codec_configure(struct azx *chip);
  int azx_init_streams(struct azx *chip);
@@@ -46,6 -46,7 +46,7 @@@
  #include <sound/initval.h>
  #include <sound/hdaudio.h>
  #include <sound/hda_i915.h>
+ #include <sound/intel-nhlt.h>
  #include <linux/vgaarb.h>
  #include <linux/vga_switcheroo.h>
  #include <linux/firmware.h>
@@@ -64,7 -65,6 +65,7 @@@ enum 
        POS_FIX_VIACOMBO,
        POS_FIX_COMBO,
        POS_FIX_SKL,
 +      POS_FIX_FIFO,
  };
  
  /* Defines for ATI HD Audio support in SB450 south bridge */
@@@ -125,6 -125,7 +126,7 @@@ static char *patch[SNDRV_CARDS]
  static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
                                        CONFIG_SND_HDA_INPUT_BEEP_MODE};
  #endif
+ static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC);
  
  module_param_array(index, int, NULL, 0444);
  MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@@ -136,7 -137,7 +138,7 @@@ module_param_array(model, charp, NULL, 
  MODULE_PARM_DESC(model, "Use the given board model.");
  module_param_array(position_fix, int, NULL, 0444);
  MODULE_PARM_DESC(position_fix, "DMA pointer read method."
 -               "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+).");
 +               "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
  module_param_array(bdl_pos_adj, int, NULL, 0644);
  MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
  module_param_array(probe_mask, int, NULL, 0444);
@@@ -159,6 -160,8 +161,8 @@@ module_param_array(beep_mode, bool, NUL
  MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
                            "(0=off, 1=on) (default=1).");
  #endif
+ module_param(dmic_detect, bool, 0444);
+ MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms");
  
  #ifdef CONFIG_PM
  static int param_set_xint(const char *val, const struct kernel_param *kp);
@@@ -314,10 -317,11 +318,10 @@@ enum 
  
  #define AZX_DCAPS_INTEL_SKYLAKE \
        (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
 +       AZX_DCAPS_SYNC_WRITE |\
         AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
  
 -#define AZX_DCAPS_INTEL_BROXTON \
 -      (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
 -       AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
 +#define AZX_DCAPS_INTEL_BROXTON               AZX_DCAPS_INTEL_SKYLAKE
  
  /* quirks for ATI SB / AMD Hudson */
  #define AZX_DCAPS_PRESET_ATI_SB \
  #define AZX_DCAPS_PRESET_ATI_HDMI_NS \
        (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
  
 +/* quirks for AMD SB */
 +#define AZX_DCAPS_PRESET_AMD_SB \
 +      (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\
 +       AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME)
 +
  /* quirks for Nvidia */
  #define AZX_DCAPS_PRESET_NVIDIA \
        (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
@@@ -847,49 -846,6 +851,49 @@@ static unsigned int azx_via_get_positio
        return bound_pos + mod_dma_pos;
  }
  
 +#define AMD_FIFO_SIZE 32
 +
 +/* get the current DMA position with FIFO size correction */
 +static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
 +{
 +      struct snd_pcm_substream *substream = azx_dev->core.substream;
 +      struct snd_pcm_runtime *runtime = substream->runtime;
 +      unsigned int pos, delay;
 +
 +      pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
 +      if (!runtime)
 +              return pos;
 +
 +      runtime->delay = AMD_FIFO_SIZE;
 +      delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
 +      if (azx_dev->insufficient) {
 +              if (pos < delay) {
 +                      delay = pos;
 +                      runtime->delay = bytes_to_frames(runtime, pos);
 +              } else {
 +                      azx_dev->insufficient = 0;
 +              }
 +      }
 +
 +      /* correct the DMA position for capture stream */
 +      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 +              if (pos < delay)
 +                      pos += azx_dev->core.bufsize;
 +              pos -= delay;
 +      }
 +
 +      return pos;
 +}
 +
 +static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
 +                                 unsigned int pos)
 +{
 +      struct snd_pcm_substream *substream = azx_dev->core.substream;
 +
 +      /* just read back the calculated value in the above */
 +      return substream->runtime->delay;
 +}
 +
  static unsigned int azx_skl_get_dpib_pos(struct azx *chip,
                                         struct azx_dev *azx_dev)
  {
@@@ -1466,7 -1422,6 +1470,7 @@@ static int check_position_fix(struct az
        case POS_FIX_VIACOMBO:
        case POS_FIX_COMBO:
        case POS_FIX_SKL:
 +      case POS_FIX_FIFO:
                return fix;
        }
  
                dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
                return POS_FIX_VIACOMBO;
        }
 +      if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
 +              dev_dbg(chip->card->dev, "Using FIFO position fix\n");
 +              return POS_FIX_FIFO;
 +      }
        if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
                dev_dbg(chip->card->dev, "Using LPIB position fix\n");
                return POS_FIX_LPIB;
@@@ -1507,7 -1458,6 +1511,7 @@@ static void assign_position_fix(struct 
                [POS_FIX_VIACOMBO] = azx_via_get_position,
                [POS_FIX_COMBO] = azx_get_pos_lpib,
                [POS_FIX_SKL] = azx_get_pos_skl,
 +              [POS_FIX_FIFO] = azx_get_pos_fifo,
        };
  
        chip->get_position[0] = chip->get_position[1] = callbacks[fix];
                        azx_get_delay_from_lpib;
        }
  
 +      if (fix == POS_FIX_FIFO)
 +              chip->get_delay[0] = chip->get_delay[1] =
 +                      azx_get_delay_from_fifo;
  }
  
  /*
@@@ -1684,7 -1631,6 +1688,6 @@@ static int default_bdl_pos_adj(struct a
  /*
   * constructor
   */
- static const struct hdac_io_ops pci_hda_io_ops;
  static const struct hda_controller_ops pci_hda_ops;
  
  static int azx_create(struct snd_card *card, struct pci_dev *pci,
        else
                chip->bdl_pos_adj = bdl_pos_adj[dev];
  
-       err = azx_bus_init(chip, model[dev], &pci_hda_io_ops);
+       err = azx_bus_init(chip, model[dev]);
        if (err < 0) {
                kfree(hda);
                pci_disable_device(pci);
                return err;
        }
  
+       /* use the non-cached pages in non-snoop mode */
+       if (!azx_snoop(chip))
+               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
        /* Workaround for a communication error on CFL (bko#199007) and CNL */
        if (IS_CFL(pci) || IS_CNL(pci))
                azx_bus(chip)->polling_mode = 1;
@@@ -1985,41 -1935,6 +1992,6 @@@ static void azx_firmware_cb(const struc
  }
  #endif
  
- /*
-  * HDA controller ops.
-  */
- /* PCI register access. */
- static void pci_azx_writel(u32 value, u32 __iomem *addr)
- {
-       writel(value, addr);
- }
- static u32 pci_azx_readl(u32 __iomem *addr)
- {
-       return readl(addr);
- }
- static void pci_azx_writew(u16 value, u16 __iomem *addr)
- {
-       writew(value, addr);
- }
- static u16 pci_azx_readw(u16 __iomem *addr)
- {
-       return readw(addr);
- }
- static void pci_azx_writeb(u8 value, u8 __iomem *addr)
- {
-       writeb(value, addr);
- }
- static u8 pci_azx_readb(u8 __iomem *addr)
- {
-       return readb(addr);
- }
  static int disable_msi_reset_irq(struct azx *chip)
  {
        struct hdac_bus *bus = azx_bus(chip);
        return 0;
  }
  
- /* DMA page allocation helpers.  */
- static int dma_alloc_pages(struct hdac_bus *bus,
-                          int type,
-                          size_t size,
-                          struct snd_dma_buffer *buf)
- {
-       struct azx *chip = bus_to_azx(bus);
-       if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV)
-               type = SNDRV_DMA_TYPE_DEV_UC;
-       return snd_dma_alloc_pages(type, bus->dev, size, buf);
- }
- static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
- {
-       snd_dma_free_pages(buf);
- }
  static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
                             struct vm_area_struct *area)
  {
  #endif
  }
  
- static const struct hdac_io_ops pci_hda_io_ops = {
-       .reg_writel = pci_azx_writel,
-       .reg_readl = pci_azx_readl,
-       .reg_writew = pci_azx_writew,
-       .reg_readw = pci_azx_readw,
-       .reg_writeb = pci_azx_writeb,
-       .reg_readb = pci_azx_readb,
-       .dma_alloc_pages = dma_alloc_pages,
-       .dma_free_pages = dma_free_pages,
- };
  static const struct hda_controller_ops pci_hda_ops = {
        .disable_msi_reset_irq = disable_msi_reset_irq,
        .pcm_mmap_prepare = pcm_mmap_prepare,
        .position_check = azx_position_check,
  };
  
+ static int azx_check_dmic(struct pci_dev *pci, struct azx *chip)
+ {
+       struct nhlt_acpi_table *nhlt;
+       int ret = 0;
+       if (chip->driver_type == AZX_DRIVER_SKL &&
+           pci->class != 0x040300) {
+               nhlt = intel_nhlt_init(&pci->dev);
+               if (nhlt) {
+                       if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) {
+                               ret = -ENODEV;
+                               dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n");
+                       }
+                       intel_nhlt_free(nhlt);
+               }
+       }
+       return ret;
+ }
  static int azx_probe(struct pci_dev *pci,
                     const struct pci_device_id *pci_id)
  {
        card->private_data = chip;
        hda = container_of(chip, struct hda_intel, chip);
  
+       /*
+        * stop probe if digital microphones detected on Skylake+ platform
+        * with the DSP enabled. This is an opt-in behavior defined at build
+        * time or at run-time with a module parameter
+        */
+       if (dmic_detect) {
+               err = azx_check_dmic(pci, chip);
+               if (err < 0)
+                       goto out_free;
+       }
        pci_set_drvdata(pci, card);
  
        err = register_vga_switcheroo(chip);
@@@ -2505,12 -2421,6 +2478,12 @@@ static const struct pci_device_id azx_i
        /* AMD Hudson */
        { PCI_DEVICE(0x1022, 0x780d),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
 +      /* AMD, X370 & co */
 +      { PCI_DEVICE(0x1022, 0x1457),
 +        .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
 +      /* AMD, X570 & co */
 +      { PCI_DEVICE(0x1022, 0x1487),
 +        .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
        /* AMD Stoney */
        { PCI_DEVICE(0x1022, 0x157a),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
@@@ -392,11 -392,11 +392,11 @@@ static int mchp_i2s_mcc_clk_get_rate_di
  }
  
  static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
-                                   unsigned int bclk, unsigned int *mra)
+                                   unsigned int bclk, unsigned int *mra,
+                                   unsigned long *best_rate)
  {
        unsigned long clk_rate;
        unsigned long lcm_rate;
-       unsigned long best_rate = 0;
        unsigned long best_diff_rate = ~0;
        unsigned int sysclk;
        struct clk *best_clk = NULL;
             (clk_rate == bclk || clk_rate / (bclk * 2) <= GENMASK(5, 0));
             clk_rate += lcm_rate) {
                ret = mchp_i2s_mcc_clk_get_rate_diff(dev->gclk, clk_rate,
-                                                    &best_clk, &best_rate,
+                                                    &best_clk, best_rate,
                                                     &best_diff_rate);
                if (ret) {
                        dev_err(dev->dev, "gclk error for rate %lu: %d",
                }
  
                ret = mchp_i2s_mcc_clk_get_rate_diff(dev->pclk, clk_rate,
-                                                    &best_clk, &best_rate,
+                                                    &best_clk, best_rate,
                                                     &best_diff_rate);
                if (ret) {
                        dev_err(dev->dev, "pclk error for rate %lu: %d",
  
        dev_dbg(dev->dev, "source CLK is %s with rate %lu, diff %lu\n",
                best_clk == dev->pclk ? "pclk" : "gclk",
-               best_rate, best_diff_rate);
-       /* set the rate */
-       ret = clk_set_rate(best_clk, best_rate);
-       if (ret) {
-               dev_err(dev->dev, "unable to set rate %lu to %s: %d\n",
-                       best_rate, best_clk == dev->pclk ? "PCLK" : "GCLK",
-                       ret);
-               return ret;
-       }
+               *best_rate, best_diff_rate);
  
        /* Configure divisors */
        if (dev->sysclk)
-               *mra |= MCHP_I2SMCC_MRA_IMCKDIV(best_rate / (2 * sysclk));
-       *mra |= MCHP_I2SMCC_MRA_ISCKDIV(best_rate / (2 * bclk));
+               *mra |= MCHP_I2SMCC_MRA_IMCKDIV(*best_rate / (2 * sysclk));
+       *mra |= MCHP_I2SMCC_MRA_ISCKDIV(*best_rate / (2 * bclk));
  
-       if (best_clk == dev->gclk) {
+       if (best_clk == dev->gclk)
                *mra |= MCHP_I2SMCC_MRA_SRCCLK_GCLK;
-               ret = clk_prepare(dev->gclk);
-               if (ret < 0)
-                       dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret);
-               else
-                       dev->gclk_use = 1;
-       } else {
+       else
                *mra |= MCHP_I2SMCC_MRA_SRCCLK_PCLK;
-               dev->gclk_use = 0;
-       }
  
        return 0;
  }
@@@ -502,6 -486,7 +486,7 @@@ static int mchp_i2s_mcc_hw_params(struc
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
  {
+       unsigned long rate = 0;
        struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai);
        u32 mra = 0;
        u32 mrb = 0;
                return -EINVAL;
        }
  
+       if (set_divs) {
+               bclk_rate = frame_length * params_rate(params);
+               ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra,
+                                              &rate);
+               if (ret) {
+                       dev_err(dev->dev,
+                               "unable to configure the divisors: %d\n", ret);
+                       return ret;
+               }
+       }
        /*
         * If we are already running, the wanted setup must be
         * the same with the one that's currently ongoing
                return 0;
        }
  
-       /* Save the number of channels to know what interrupts to enable */
-       dev->channels = channels;
-       if (set_divs) {
-               bclk_rate = frame_length * params_rate(params);
-               ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra);
+       if (mra & MCHP_I2SMCC_MRA_SRCCLK_GCLK && !dev->gclk_use) {
+               /* set the rate */
+               ret = clk_set_rate(dev->gclk, rate);
                if (ret) {
-                       dev_err(dev->dev, "unable to configure the divisors: %d\n",
-                               ret);
+                       dev_err(dev->dev,
+                               "unable to set rate %lu to GCLK: %d\n",
+                               rate, ret);
                        return ret;
                }
+               ret = clk_prepare(dev->gclk);
+               if (ret < 0) {
+                       dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret);
+                       return ret;
+               }
+               dev->gclk_use = 1;
        }
  
+       /* Save the number of channels to know what interrupts to enable */
+       dev->channels = channels;
        ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra);
 -      if (ret < 0)
 +      if (ret < 0) {
 +              if (dev->gclk_use) {
 +                      clk_unprepare(dev->gclk);
 +                      dev->gclk_use = 0;
 +              }
                return ret;
 +      }
        return regmap_write(dev->regmap, MCHP_I2SMCC_MRB, mrb);
  }
  
@@@ -691,37 -690,31 +695,37 @@@ static int mchp_i2s_mcc_hw_free(struct 
                err = wait_event_interruptible_timeout(dev->wq_txrdy,
                                                       dev->tx_rdy,
                                                       msecs_to_jiffies(500));
 +              if (err == 0) {
 +                      dev_warn_once(dev->dev,
 +                                    "Timeout waiting for Tx ready\n");
 +                      regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
 +                                   MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
 +                      dev->tx_rdy = 1;
 +              }
        } else {
                err = wait_event_interruptible_timeout(dev->wq_rxrdy,
                                                       dev->rx_rdy,
                                                       msecs_to_jiffies(500));
 -      }
 -
 -      if (err == 0) {
 -              u32 idra;
 -
 -              dev_warn_once(dev->dev, "Timeout waiting for %s\n",
 -                            is_playback ? "Tx ready" : "Rx ready");
 -              if (is_playback)
 -                      idra = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels);
 -              else
 -                      idra = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels);
 -              regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
 +              if (err == 0) {
 +                      dev_warn_once(dev->dev,
 +                                    "Timeout waiting for Rx ready\n");
 +                      regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
 +                                   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
 +                      dev->rx_rdy = 1;
 +              }
        }
  
        if (!mchp_i2s_mcc_is_running(dev)) {
                regmap_write(dev->regmap, MCHP_I2SMCC_CR, MCHP_I2SMCC_CR_CKDIS);
  
                if (dev->gclk_running) {
 -                      clk_disable_unprepare(dev->gclk);
 +                      clk_disable(dev->gclk);
                        dev->gclk_running = 0;
                }
 +              if (dev->gclk_use) {
 +                      clk_unprepare(dev->gclk);
 +                      dev->gclk_use = 0;
 +              }
        }
  
        return 0;
@@@ -820,8 -813,6 +824,8 @@@ static int mchp_i2s_mcc_dai_probe(struc
  
        init_waitqueue_head(&dev->wq_txrdy);
        init_waitqueue_head(&dev->wq_rxrdy);
 +      dev->tx_rdy = 1;
 +      dev->rx_rdy = 1;
  
        snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
  
@@@ -9,6 -9,7 +9,7 @@@
  
  #include <linux/module.h>
  #include <linux/acpi.h>
+ #include <linux/clk.h>
  #include <linux/delay.h>
  #include <linux/i2c.h>
  #include <linux/mod_devicetable.h>
@@@ -33,6 -34,7 +34,7 @@@ static const unsigned int supported_mcl
  
  struct es8316_priv {
        struct mutex lock;
+       struct clk *mclk;
        struct regmap *regmap;
        struct snd_soc_component *component;
        struct snd_soc_jack *jack;
@@@ -51,10 -53,7 +53,10 @@@ static const SNDRV_CTL_TLVD_DECLARE_DB_
  static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
  static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
  static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
 -static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
 +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
 +      0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
 +      8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
 +);
  
  static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
        0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
@@@ -92,7 -91,7 +94,7 @@@ static const struct snd_kcontrol_new es
        SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
                       4, 0, 3, 1, hpout_vol_tlv),
        SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
 -                     0, 4, 7, 0, hpmixer_gain_tlv),
 +                     4, 0, 11, 0, hpmixer_gain_tlv),
  
        SOC_ENUM("Playback Polarity", dacpol),
        SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
@@@ -363,13 -362,21 +365,21 @@@ static int es8316_set_dai_sysclk(struc
  {
        struct snd_soc_component *component = codec_dai->component;
        struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
-       int i;
+       int i, ret;
        int count = 0;
  
        es8316->sysclk = freq;
  
-       if (freq == 0)
+       if (freq == 0) {
+               es8316->sysclk_constraints.list = NULL;
+               es8316->sysclk_constraints.count = 0;
                return 0;
+       }
+       ret = clk_set_rate(es8316->mclk, freq);
+       if (ret)
+               return ret;
  
        /* Limit supported sample rates to ones that can be autodetected
         * by the codec running in slave mode.
@@@ -444,17 -451,10 +454,10 @@@ static int es8316_pcm_startup(struct sn
        struct snd_soc_component *component = dai->component;
        struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
  
-       if (es8316->sysclk == 0) {
-               dev_err(component->dev, "No sysclk provided\n");
-               return -EINVAL;
-       }
-       /* The set of sample rates that can be supported depends on the
-        * MCLK supplied to the CODEC.
-        */
-       snd_pcm_hw_constraint_list(substream->runtime, 0,
-                                  SNDRV_PCM_HW_PARAM_RATE,
-                                  &es8316->sysclk_constraints);
+       if (es8316->sysclk_constraints.list)
+               snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                          SNDRV_PCM_HW_PARAM_RATE,
+                                          &es8316->sysclk_constraints);
  
        return 0;
  }
@@@ -466,11 -466,19 +469,19 @@@ static int es8316_pcm_hw_params(struct 
        struct snd_soc_component *component = dai->component;
        struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
        u8 wordlen = 0;
+       int i;
  
-       if (!es8316->sysclk) {
-               dev_err(component->dev, "No MCLK configured\n");
-               return -EINVAL;
+       /* Validate supported sample rates that are autodetected from MCLK */
+       for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
+               const unsigned int ratio = supported_mclk_lrck_ratios[i];
+               if (es8316->sysclk % ratio != 0)
+                       continue;
+               if (es8316->sysclk / ratio == params_rate(params))
+                       break;
        }
+       if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
+               return -EINVAL;
  
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@@ -700,9 -708,24 +711,24 @@@ static int es8316_set_jack(struct snd_s
  static int es8316_probe(struct snd_soc_component *component)
  {
        struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
+       int ret;
  
        es8316->component = component;
  
+       es8316->mclk = devm_clk_get_optional(component->dev, "mclk");
+       if (IS_ERR(es8316->mclk)) {
+               dev_err(component->dev, "unable to get mclk\n");
+               return PTR_ERR(es8316->mclk);
+       }
+       if (!es8316->mclk)
+               dev_warn(component->dev, "assuming static mclk\n");
+       ret = clk_prepare_enable(es8316->mclk);
+       if (ret) {
+               dev_err(component->dev, "unable to enable mclk\n");
+               return ret;
+       }
        /* Reset codec and enable current state machine */
        snd_soc_component_write(component, ES8316_RESET, 0x3f);
        usleep_range(5000, 5500);
        return 0;
  }
  
+ static void es8316_remove(struct snd_soc_component *component)
+ {
+       struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
+       clk_disable_unprepare(es8316->mclk);
+ }
  static const struct snd_soc_component_driver soc_component_dev_es8316 = {
        .probe                  = es8316_probe,
+       .remove                 = es8316_remove,
        .set_jack               = es8316_set_jack,
        .controls               = es8316_snd_controls,
        .num_controls           = ARRAY_SIZE(es8316_snd_controls),
@@@ -978,9 -978,6 +978,6 @@@ static bool rt1011_readable_register(st
        }
  }
  
- static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9435, 37, 0);
- static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1739, 37, 0);
  static const char * const rt1011_din_source_select[] = {
        "Left",
        "Right",
@@@ -1029,6 -1026,8 +1026,8 @@@ static const char * const rt1011_tdm_ad
  
  static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum,   RT1011_TDM1_SET_3, 6,
        rt1011_tdm_adc_swap_select);
+ static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum,   RT1011_TDM1_SET_3, 4,
+       rt1011_tdm_adc_swap_select);
  
  static void rt1011_reset(struct regmap *regmap)
  {
@@@ -1223,7 -1222,10 +1222,10 @@@ static int rt1011_bq_drc_info(struct sn
  static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
  {
-       ucontrol->value.integer.value[0] = 0;
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
+       ucontrol->value.integer.value[0] = rt1011->cali_done;
  
        return 0;
  }
@@@ -1237,6 -1239,7 +1239,7 @@@ static int rt1011_r0_cali_put(struct sn
        if (!component->card->instantiated)
                return 0;
  
+       rt1011->cali_done = 0;
        if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF &&
                ucontrol->value.integer.value[0])
                rt1011_calibrate(rt1011, 1);
@@@ -1333,7 -1336,8 +1336,8 @@@ static const struct snd_kcontrol_new rt
        /* TDM1 Data Out Selection */
        SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum),
        SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum),
-       SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum),
+       SOC_ENUM("TDM1 ADC1DAT Swap Select", rt1011_tdm_adc1_1_enum),
+       SOC_ENUM("TDM1 ADC2DAT Swap Select", rt1011_tdm_adc2_1_enum),
  
        /* Data Out Mode */
        SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum),
        SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0,
                rt1011_r0_cali_get, rt1011_r0_cali_put),
        RT1011_R0_LOAD("R0 Load Mode"),
+       /* R0 temperature */
+       SOC_SINGLE("R0 Temperature", RT1011_STP_INITIAL_RESISTANCE_TEMP,
+               2, 255, 0),
  };
  
  static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
@@@ -1511,7 -1519,8 +1519,8 @@@ static const struct snd_soc_dapm_route 
  
  static int rt1011_get_clk_info(int sclk, int rate)
  {
-       int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
+       int i;
+       static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
  
        if (sclk <= 0 || rate <= 0)
                return -EINVAL;
@@@ -1619,18 -1628,14 +1628,18 @@@ static int rt1011_hw_params(struct snd_
  static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  {
        struct snd_soc_component *component = dai->component;
 +      struct snd_soc_dapm_context *dapm =
 +              snd_soc_component_get_dapm(component);
        unsigned int reg_val = 0, reg_bclk_inv = 0;
 +      int ret = 0;
  
 +      snd_soc_dapm_mutex_lock(dapm);
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                reg_val |= RT1011_I2S_TDM_MS_S;
                break;
        default:
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
  
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
                reg_bclk_inv |= RT1011_TDM_INV_BCLK;
                break;
        default:
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
  
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
                reg_val |= RT1011_I2S_TDM_DF_PCM_B;
                break;
        default:
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
  
        switch (dai->id) {
                break;
        default:
                dev_err(component->dev, "Invalid dai->id: %d\n", dai->id);
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
 -      return 0;
 +
 +      snd_soc_dapm_mutex_unlock(dapm);
 +      return ret;
  }
  
  static int rt1011_set_component_sysclk(struct snd_soc_component *component,
@@@ -1794,12 -1797,8 +1803,12 @@@ static int rt1011_set_tdm_slot(struct s
        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
  {
        struct snd_soc_component *component = dai->component;
 +      struct snd_soc_dapm_context *dapm =
 +              snd_soc_component_get_dapm(component);
        unsigned int val = 0, tdm_en = 0;
 +      int ret = 0;
  
 +      snd_soc_dapm_mutex_lock(dapm);
        if (rx_mask || tx_mask)
                tdm_en = RT1011_TDM_I2S_DOCK_EN_1;
  
        case 2:
                break;
        default:
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
  
        switch (slot_width) {
        case 16:
                break;
        default:
 -              return -EINVAL;
 +              ret = -EINVAL;
        }
  
        snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
                RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
                RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
  
 -      return 0;
 +      snd_soc_dapm_mutex_unlock(dapm);
 +      return ret;
  }
  
  static int rt1011_probe(struct snd_soc_component *component)
@@@ -2139,6 -2137,7 +2148,7 @@@ static int rt1011_calibrate(struct rt10
                        r0_factor = ((format / r0[0] * 100) / 128)
                                                        - (r0_integer * 100);
                        rt1011->r0_reg = r0[0];
+                       rt1011->cali_done = 1;
                        dev_info(dev,   "r0 resistance about %d.%02d ohm, reg=0x%X\n",
                                r0_integer, r0_factor, r0[0]);
                }
@@@ -2189,6 -2188,13 +2199,13 @@@ static void rt1011_calibration_work(str
  
        rt1011_calibrate(rt1011, 1);
  
+       /*
+        * This flag should reset after booting.
+        * The factory test will do calibration again and use this flag to check
+        * whether the calibration completed
+        */
+       rt1011->cali_done = 0;
        /* initial */
        rt1011_reg_init(component);
  }
diff --combined sound/soc/fsl/fsl_ssi.c
@@@ -799,6 -799,15 +799,6 @@@ static int fsl_ssi_hw_params(struct snd
        u32 wl = SSI_SxCCR_WL(sample_size);
        int ret;
  
 -      /*
 -       * SSI is properly configured if it is enabled and running in
 -       * the synchronous mode; Note that AC97 mode is an exception
 -       * that should set separate configurations for STCCR and SRCCR
 -       * despite running in the synchronous mode.
 -       */
 -      if (ssi->streams && ssi->synchronous)
 -              return 0;
 -
        if (fsl_ssi_is_i2s_master(ssi)) {
                ret = fsl_ssi_set_bclk(substream, dai, hw_params);
                if (ret)
                }
        }
  
 +      /*
 +       * SSI is properly configured if it is enabled and running in
 +       * the synchronous mode; Note that AC97 mode is an exception
 +       * that should set separate configurations for STCCR and SRCCR
 +       * despite running in the synchronous mode.
 +       */
 +      if (ssi->streams && ssi->synchronous)
 +              return 0;
 +
        if (!fsl_ssi_is_ac97(ssi)) {
                /*
                 * Keep the ssi->i2s_net intact while having a local variable
@@@ -1510,10 -1510,8 +1510,8 @@@ static int fsl_ssi_probe(struct platfor
        }
  
        ssi->irq = platform_get_irq(pdev, 0);
-       if (ssi->irq < 0) {
-               dev_err(dev, "no irq for node %s\n", pdev->name);
+       if (ssi->irq < 0)
                return ssi->irq;
-       }
  
        /* Set software limitations for synchronous mode except AC97 */
        if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) {
@@@ -43,7 -43,7 +43,7 @@@ static struct ipc_message *msg_get_empt
  }
  
  static int tx_wait_done(struct sst_generic_ipc *ipc,
-       struct ipc_message *msg, void *rx_data)
+       struct ipc_message *msg, struct sst_ipc_message *reply)
  {
        unsigned long flags;
        int ret;
        } else {
  
                /* copy the data returned from DSP */
-               if (rx_data)
-                       memcpy(rx_data, msg->rx_data, msg->rx_size);
+               if (reply) {
+                       reply->header = msg->rx.header;
+                       if (reply->data)
+                               memcpy(reply->data, msg->rx.data, msg->rx.size);
+               }
                ret = msg->errno;
        }
  
@@@ -72,9 -75,9 +75,9 @@@
        return ret;
  }
  
- static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
-       void *tx_data, size_t tx_bytes, void *rx_data,
-       size_t rx_bytes, int wait)
+ static int ipc_tx_message(struct sst_generic_ipc *ipc,
+       struct sst_ipc_message request,
+       struct sst_ipc_message *reply, int wait)
  {
        struct ipc_message *msg;
        unsigned long flags;
                return -EBUSY;
        }
  
-       msg->header = header;
-       msg->tx_size = tx_bytes;
-       msg->rx_size = rx_bytes;
+       msg->tx.header = request.header;
+       msg->tx.size = request.size;
+       msg->rx.header = 0;
+       msg->rx.size = reply ? reply->size : 0;
        msg->wait = wait;
        msg->errno = 0;
        msg->pending = false;
        msg->complete = false;
  
-       if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL))
-               ipc->ops.tx_data_copy(msg, tx_data, tx_bytes);
+       if ((request.size) && (ipc->ops.tx_data_copy != NULL))
+               ipc->ops.tx_data_copy(msg, request.data, request.size);
  
        list_add_tail(&msg->list, &ipc->tx_list);
        schedule_work(&ipc->kwork);
        spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
  
        if (wait)
-               return tx_wait_done(ipc, msg, rx_data);
+               return tx_wait_done(ipc, msg, reply);
        else
                return 0;
  }
@@@ -118,13 -122,13 +122,13 @@@ static int msg_empty_list_init(struct s
                return -ENOMEM;
  
        for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
-               ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
-               if (ipc->msg[i].tx_data == NULL)
+               ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
+               if (ipc->msg[i].tx.data == NULL)
                        goto free_mem;
  
-               ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
-               if (ipc->msg[i].rx_data == NULL) {
-                       kfree(ipc->msg[i].tx_data);
+               ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
+               if (ipc->msg[i].rx.data == NULL) {
+                       kfree(ipc->msg[i].tx.data);
                        goto free_mem;
                }
  
  
  free_mem:
        while (i > 0) {
-               kfree(ipc->msg[i-1].tx_data);
-               kfree(ipc->msg[i-1].rx_data);
+               kfree(ipc->msg[i-1].tx.data);
+               kfree(ipc->msg[i-1].rx.data);
                --i;
        }
        kfree(ipc->msg);
@@@ -173,8 -177,8 +177,8 @@@ static void ipc_tx_msgs(struct work_str
        spin_unlock_irq(&ipc->dsp->spinlock);
  }
  
- int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
-       void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
+ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
+       struct sst_ipc_message request, struct sst_ipc_message *reply)
  {
        int ret;
  
                if (ipc->ops.check_dsp_lp_on(ipc->dsp, true))
                        return -EIO;
  
-       ret = ipc_tx_message(ipc, header, tx_data, tx_bytes,
-               rx_data, rx_bytes, 1);
+       ret = ipc_tx_message(ipc, request, reply, 1);
  
        if (ipc->ops.check_dsp_lp_on)
                if (ipc->ops.check_dsp_lp_on(ipc->dsp, false))
  }
  EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
  
- int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
-       void *tx_data, size_t tx_bytes)
+ int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
+       struct sst_ipc_message request)
  {
-       return ipc_tx_message(ipc, header, tx_data, tx_bytes,
-               NULL, 0, 0);
+       return ipc_tx_message(ipc, request, NULL, 0);
  }
  EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
  
- int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header,
-       void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
+ int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
+       struct sst_ipc_message request, struct sst_ipc_message *reply)
  {
-       return ipc_tx_message(ipc, header, tx_data, tx_bytes,
-               rx_data, rx_bytes, 1);
+       return ipc_tx_message(ipc, request, reply, 1);
  }
  EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm);
  
@@@ -222,8 -223,6 +223,8 @@@ struct ipc_message *sst_ipc_reply_find_
  
        if (ipc->ops.reply_msg_match != NULL)
                header = ipc->ops.reply_msg_match(header, &mask);
 +      else
 +              mask = (u64)-1;
  
        if (list_empty(&ipc->rx_list)) {
                dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
        }
  
        list_for_each_entry(msg, &ipc->rx_list, list) {
-               if ((msg->header & mask) == header)
+               if ((msg->tx.header & mask) == header)
                        return msg;
        }
  
@@@ -306,8 -305,8 +307,8 @@@ void sst_ipc_fini(struct sst_generic_ip
  
        if (ipc->msg) {
                for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
-                       kfree(ipc->msg[i].tx_data);
-                       kfree(ipc->msg[i].rx_data);
+                       kfree(ipc->msg[i].tx.data);
+                       kfree(ipc->msg[i].rx.data);
                }
                kfree(ipc->msg);
        }
@@@ -20,7 -20,7 +20,7 @@@
  #define FW_REG_SIZE   0x60
  
  struct skl_debug {
-       struct skl *skl;
+       struct skl_dev *skl;
        struct device *dev;
  
        struct dentry *fs;
@@@ -66,6 -66,8 +66,8 @@@ static ssize_t module_read(struct file 
                           size_t count, loff_t *ppos)
  {
        struct skl_module_cfg *mconfig = file->private_data;
+       struct skl_module *module = mconfig->module;
+       struct skl_module_res *res = &module->resources[mconfig->res_idx];
        char *buf;
        ssize_t ret;
  
@@@ -79,8 -81,8 +81,8 @@@
                        mconfig->id.pvt_id);
  
        ret += snprintf(buf + ret, MOD_BUF - ret,
-                       "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n",
-                       mconfig->mcps, mconfig->ibs, mconfig->obs);
+                       "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n",
+                       res->cpc, res->ibs, res->obs);
  
        ret += snprintf(buf + ret, MOD_BUF - ret,
                        "Module data:\n\tCore %d\n\tIn queue %d\n\t"
@@@ -162,17 -164,15 +164,15 @@@ void skl_debug_init_module(struct skl_d
                        struct snd_soc_dapm_widget *w,
                        struct skl_module_cfg *mconfig)
  {
-       if (!debugfs_create_file(w->name, 0444,
-                               d->modules, mconfig,
-                               &mcfg_fops))
-               dev_err(d->dev, "%s: module debugfs init failed\n", w->name);
+       debugfs_create_file(w->name, 0444, d->modules, mconfig,
+                           &mcfg_fops);
  }
  
  static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
                               size_t count, loff_t *ppos)
  {
        struct skl_debug *d = file->private_data;
-       struct sst_dsp *sst = d->skl->skl_sst->dsp;
+       struct sst_dsp *sst = d->skl->dsp;
        size_t w0_stat_sz = sst->addr.w0_stat_sz;
        void __iomem *in_base = sst->mailbox.in_base;
        void __iomem *fw_reg_addr;
        memset(d->fw_read_buff, 0, FW_REG_BUF);
  
        if (w0_stat_sz > 0)
 -              __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
 +              __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
  
        for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
                ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
@@@ -213,7 -213,7 +213,7 @@@ static const struct file_operations sof
        .llseek = default_llseek,
  };
  
- struct skl_debug *skl_debugfs_init(struct skl *skl)
+ struct skl_debug *skl_debugfs_init(struct skl_dev *skl)
  {
        struct skl_debug *d;
  
                return NULL;
  
        /* create the debugfs dir with platform component's debugfs as parent */
-       d->fs = debugfs_create_dir("dsp",
-                                  skl->component->debugfs_root);
-       if (IS_ERR(d->fs) || !d->fs) {
-               dev_err(&skl->pci->dev, "debugfs root creation failed\n");
-               return NULL;
-       }
+       d->fs = debugfs_create_dir("dsp", skl->component->debugfs_root);
  
        d->skl = skl;
        d->dev = &skl->pci->dev;
  
        /* now create the module dir */
        d->modules = debugfs_create_dir("modules", d->fs);
-       if (IS_ERR(d->modules) || !d->modules) {
-               dev_err(&skl->pci->dev, "modules debugfs create failed\n");
-               goto err;
-       }
  
-       if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d,
-                                &soft_regs_ctrl_fops)) {
-               dev_err(d->dev, "fw soft regs control debugfs init failed\n");
-               goto err;
-       }
+       debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d,
+                           &soft_regs_ctrl_fops);
  
        return d;
- err:
-       debugfs_remove_recursive(d->fs);
-       return NULL;
  }
  
- void skl_debugfs_exit(struct skl *skl)
+ void skl_debugfs_exit(struct skl_dev *skl)
  {
        struct skl_debug *d = skl->debugfs;
  
@@@ -9,57 -9,10 +9,10 @@@
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  #include <linux/pci.h>
+ #include <sound/intel-nhlt.h>
  #include "skl.h"
  #include "skl-i2s.h"
  
- #define NHLT_ACPI_HEADER_SIG  "NHLT"
- /* Unique identification for getting NHLT blobs */
- static guid_t osc_guid =
-       GUID_INIT(0xA69F886E, 0x6CEB, 0x4594,
-                 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53);
- struct nhlt_acpi_table *skl_nhlt_init(struct device *dev)
- {
-       acpi_handle handle;
-       union acpi_object *obj;
-       struct nhlt_resource_desc  *nhlt_ptr = NULL;
-       struct nhlt_acpi_table *nhlt_table = NULL;
-       handle = ACPI_HANDLE(dev);
-       if (!handle) {
-               dev_err(dev, "Didn't find ACPI_HANDLE\n");
-               return NULL;
-       }
-       obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL);
-       if (obj && obj->type == ACPI_TYPE_BUFFER) {
-               nhlt_ptr = (struct nhlt_resource_desc  *)obj->buffer.pointer;
-               if (nhlt_ptr->length)
-                       nhlt_table = (struct nhlt_acpi_table *)
-                               memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
-                               MEMREMAP_WB);
-               ACPI_FREE(obj);
-               if (nhlt_table && (strncmp(nhlt_table->header.signature,
-                                       NHLT_ACPI_HEADER_SIG,
-                                       strlen(NHLT_ACPI_HEADER_SIG)) != 0)) {
-                       memunmap(nhlt_table);
-                       dev_err(dev, "NHLT ACPI header signature incorrect\n");
-                       return NULL;
-               }
-               return nhlt_table;
-       }
-       dev_err(dev, "device specific method to extract NHLT blob failed\n");
-       return NULL;
- }
- void skl_nhlt_free(struct nhlt_acpi_table *nhlt)
- {
-       memunmap((void *) nhlt);
- }
  static struct nhlt_specific_cfg *skl_get_specific_cfg(
                struct device *dev, struct nhlt_fmt *fmt,
                u8 no_ch, u32 rate, u16 bps, u8 linktype)
@@@ -126,7 -79,7 +79,7 @@@ static bool skl_check_ep_match(struct d
  }
  
  struct nhlt_specific_cfg
- *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type,
+ *skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type,
                        u8 s_fmt, u8 num_ch, u32 s_rate,
                        u8 dirn, u8 dev_type)
  {
        return NULL;
  }
  
- int skl_get_dmic_geo(struct skl *skl)
- {
-       struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
-       struct nhlt_endpoint *epnt;
-       struct nhlt_dmic_array_config *cfg;
-       struct device *dev = &skl->pci->dev;
-       unsigned int dmic_geo = 0;
-       u8 j;
-       if (!nhlt)
-               return 0;
-       epnt = (struct nhlt_endpoint *)nhlt->desc;
-       for (j = 0; j < nhlt->endpoint_count; j++) {
-               if (epnt->linktype == NHLT_LINK_DMIC) {
-                       cfg = (struct nhlt_dmic_array_config  *)
-                                       (epnt->config.caps);
-                       switch (cfg->array_type) {
-                       case NHLT_MIC_ARRAY_2CH_SMALL:
-                       case NHLT_MIC_ARRAY_2CH_BIG:
-                               dmic_geo |= MIC_ARRAY_2CH;
-                               break;
-                       case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
-                       case NHLT_MIC_ARRAY_4CH_L_SHAPED:
-                       case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
-                               dmic_geo |= MIC_ARRAY_4CH;
-                               break;
-                       default:
-                               dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
-                                               cfg->array_type);
-                       }
-               }
-               epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
-       }
-       return dmic_geo;
- }
  static void skl_nhlt_trim_space(char *trim)
  {
        char *s = trim;
        s[cnt] = '\0';
  }
  
- int skl_nhlt_update_topology_bin(struct skl *skl)
+ int skl_nhlt_update_topology_bin(struct skl_dev *skl)
  {
        struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
        struct hdac_bus *bus = skl_to_bus(skl);
        struct device *dev = bus->dev;
  
 -      dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n",
 +      dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n",
                nhlt->header.oem_id, nhlt->header.oem_table_id,
                nhlt->header.oem_revision);
  
@@@ -243,7 -154,7 +154,7 @@@ static ssize_t skl_nhlt_platform_id_sho
  {
        struct pci_dev *pci = to_pci_dev(dev);
        struct hdac_bus *bus = pci_get_drvdata(pci);
-       struct skl *skl = bus_to_skl(bus);
+       struct skl_dev *skl = bus_to_skl(bus);
        struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
        char platform_id[32];
  
  
  static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL);
  
- int skl_nhlt_create_sysfs(struct skl *skl)
+ int skl_nhlt_create_sysfs(struct skl_dev *skl)
  {
        struct device *dev = &skl->pci->dev;
  
        return 0;
  }
  
- void skl_nhlt_remove_sysfs(struct skl *skl)
+ void skl_nhlt_remove_sysfs(struct skl_dev *skl)
  {
        struct device *dev = &skl->pci->dev;
  
   * stores all possible rates supported in a rate table for the corresponding
   * sclk/sclkfs.
   */
- static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks,
+ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
                                struct nhlt_fmt *fmt, u8 id)
  {
        struct skl_i2s_config_blob_ext *i2s_config_ext;
        }
  }
  
- static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk,
+ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
                                struct nhlt_fmt *fmt, u8 id)
  {
        struct skl_i2s_config_blob_ext *i2s_config_ext;
        mclk[id].parent_name = parent->name;
  }
  
- void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks)
+ void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks)
  {
        struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
        struct nhlt_endpoint *epnt;
diff --combined sound/soc/soc-topology.c
@@@ -80,6 -80,12 +80,6 @@@ struct soc_tplg 
  
  static int soc_tplg_process_headers(struct soc_tplg *tplg);
  static void soc_tplg_complete(struct soc_tplg *tplg);
 -struct snd_soc_dapm_widget *
 -snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
 -                       const struct snd_soc_dapm_widget *widget);
 -struct snd_soc_dapm_widget *
 -snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 -                       const struct snd_soc_dapm_widget *widget);
  static void soc_tplg_denum_remove_texts(struct soc_enum *se);
  static void soc_tplg_denum_remove_values(struct soc_enum *se);
  
@@@ -524,7 -530,7 +524,7 @@@ static void remove_dai(struct snd_soc_c
        if (dobj->ops && dobj->ops->dai_unload)
                dobj->ops->dai_unload(comp, dobj);
  
-       list_for_each_entry(dai, &comp->dai_list, list)
+       for_each_component_dais(comp, dai)
                if (dai->driver == dai_drv)
                        dai->driver = NULL;
  
@@@ -187,9 -187,57 +187,9 @@@ static void toggle_clock(struct davinci
  static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
                struct snd_pcm_substream *substream)
  {
 -      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 -      struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        u32 spcr;
        u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
 -      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -      if (spcr & mask) {
 -              /* start off disabled */
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
 -                              spcr & ~mask);
 -              toggle_clock(dev, playback);
 -      }
 -      if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
 -                      DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
 -              /* Start the sample generator */
 -              spcr |= DAVINCI_MCBSP_SPCR_GRST;
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 -      }
 -
 -      if (playback) {
 -              /* Stop the DMA to avoid data loss */
 -              /* while the transmitter is out of reset to handle XSYNCERR */
 -              if (component->driver->ops->trigger) {
 -                      int ret = component->driver->ops->trigger(substream,
 -                              SNDRV_PCM_TRIGGER_STOP);
 -                      if (ret < 0)
 -                              printk(KERN_DEBUG "Playback DMA stop failed\n");
 -              }
 -
 -              /* Enable the transmitter */
 -              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              spcr |= DAVINCI_MCBSP_SPCR_XRST;
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 -
 -              /* wait for any unexpected frame sync error to occur */
 -              udelay(100);
 -
 -              /* Disable the transmitter to clear any outstanding XSYNCERR */
 -              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 -              toggle_clock(dev, playback);
 -
 -              /* Restart the DMA */
 -              if (component->driver->ops->trigger) {
 -                      int ret = component->driver->ops->trigger(substream,
 -                              SNDRV_PCM_TRIGGER_START);
 -                      if (ret < 0)
 -                              printk(KERN_DEBUG "Playback DMA start failed\n");
 -              }
 -      }
  
        /* Enable transmitter or receiver */
        spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@@ -527,41 -575,7 +527,41 @@@ static int davinci_i2s_prepare(struct s
  {
        struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 +      u32 spcr;
 +      u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
 +
        davinci_mcbsp_stop(dev, playback);
 +
 +      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +      if (spcr & mask) {
 +              /* start off disabled */
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
 +                                      spcr & ~mask);
 +              toggle_clock(dev, playback);
 +      }
 +      if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
 +                      DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
 +              /* Start the sample generator */
 +              spcr |= DAVINCI_MCBSP_SPCR_GRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +      }
 +
 +      if (playback) {
 +              /* Enable the transmitter */
 +              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +              spcr |= DAVINCI_MCBSP_SPCR_XRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +
 +              /* wait for any unexpected frame sync error to occur */
 +              udelay(100);
 +
 +              /* Disable the transmitter to clear any outstanding XSYNCERR */
 +              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +              spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +              toggle_clock(dev, playback);
 +      }
 +
        return 0;
  }
  
@@@ -598,6 -612,8 +598,8 @@@ static void davinci_i2s_shutdown(struc
  }
  
  #define DAVINCI_I2S_RATES     SNDRV_PCM_RATE_8000_96000
+ #define DAVINCI_I2S_FORMATS   (SNDRV_PCM_FMTBIT_S16_LE | \
+                                SNDRV_PCM_FMTBIT_S32_LE)
  
  static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
        .shutdown       = davinci_i2s_shutdown,
@@@ -625,12 -641,14 +627,14 @@@ static struct snd_soc_dai_driver davinc
                .channels_min = 2,
                .channels_max = 2,
                .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+               .formats = DAVINCI_I2S_FORMATS,
+       },
        .capture = {
                .channels_min = 2,
                .channels_max = 2,
                .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+               .formats = DAVINCI_I2S_FORMATS,
+       },
        .ops = &davinci_i2s_dai_ops,
  
  };