Merge branch 'fix/intel' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@kernel.org>
Mon, 8 Feb 2016 16:44:12 +0000 (16:44 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 8 Feb 2016 16:44:12 +0000 (16:44 +0000)
1  2 
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl.c

index f3553258091a2bd7a78f2485aaee7c46fc667758,f9297dc4b25f2106ffff4f9707384fea4489d240..b6e6b61d10ec22349650ee5c1db3074068a180e4
@@@ -25,8 -25,6 +25,8 @@@
  #include <sound/soc.h>
  #include "skl.h"
  #include "skl-topology.h"
 +#include "skl-sst-dsp.h"
 +#include "skl-sst-ipc.h"
  
  #define HDA_MONO 1
  #define HDA_STEREO 2
@@@ -38,7 -36,6 +38,7 @@@ static struct snd_pcm_hardware azx_pcm_
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 SNDRV_PCM_INFO_PAUSE |
 +                               SNDRV_PCM_INFO_RESUME |
                                 SNDRV_PCM_INFO_SYNC_START |
                                 SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
                                 SNDRV_PCM_INFO_HAS_LINK_ATIME |
@@@ -275,7 -272,6 +275,7 @@@ static void skl_pcm_close(struct snd_pc
        struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
        struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
        struct skl_dma_params *dma_params = NULL;
 +      struct skl *skl = ebus_to_skl(ebus);
  
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
  
        snd_soc_dai_set_dma_data(dai, substream, NULL);
        skl_set_suspend_active(substream, dai, false);
  
 +      /*
 +       * check if close is for "Reference Pin" and set back the
 +       * CGCTL.MISCBDCGE if disabled by driver
 +       */
 +      if (!strncmp(dai->name, "Reference Pin", 13) &&
 +                      skl->skl_sst->miscbdcg_disabled) {
 +              skl->skl_sst->enable_miscbdcge(dai->dev, true);
 +              skl->skl_sst->miscbdcg_disabled = false;
 +      }
 +
        kfree(dma_params);
  }
  
@@@ -394,15 -380,6 +394,15 @@@ static int skl_pcm_trigger(struct snd_p
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
                skl_pcm_prepare(substream, dai);
 +              /*
 +               * enable DMA Resume enable bit for the stream, set the dpib
 +               * & lpib position to resune before starting the DMA
 +               */
 +              snd_hdac_ext_stream_drsm_enable(ebus, true,
 +                                      hdac_stream(stream)->index);
 +              snd_hdac_ext_stream_set_dpibr(ebus, stream, stream->dpib);
 +              snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
 +
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                /*
                        return ret;
  
                ret = skl_decoupled_trigger(substream, cmd);
 -              if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
 +              if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) {
 +                      /* save the dpib and lpib positions */
 +                      stream->dpib = readl(ebus->bus.remap_addr +
 +                                      AZX_REG_VS_SDXDPIB_XBASE +
 +                                      (AZX_REG_VS_SDXDPIB_XINTERVAL *
 +                                      hdac_stream(stream)->index));
 +
 +                      stream->lpib = snd_hdac_stream_get_pos_lpib(
 +                                                      hdac_stream(stream));
                        snd_hdac_ext_stream_decouple(ebus, stream, false);
 +              }
                break;
  
        default:
@@@ -497,6 -465,11 +497,6 @@@ static int skl_link_pcm_prepare(struct 
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct hdac_ext_link *link;
  
 -      if (link_dev->link_prepared) {
 -              dev_dbg(dai->dev, "already stream is prepared - returning\n");
 -              return 0;
 -      }
 -
        dma_params  = (struct skl_dma_params *)
                        snd_soc_dai_get_dma_data(codec_dai, substream);
        if (dma_params)
        dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
                        hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
  
 -      snd_hdac_ext_link_stream_reset(link_dev);
 -
 -      snd_hdac_ext_link_stream_setup(link_dev, format_val);
 -
        link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
        if (!link)
                return -EINVAL;
  
 +      snd_hdac_ext_bus_link_power_up(link);
 +      snd_hdac_ext_link_stream_reset(link_dev);
 +
 +      snd_hdac_ext_link_stream_setup(link_dev, format_val);
 +
        snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
        link_dev->link_prepared = 1;
  
@@@ -524,16 -496,12 +524,16 @@@ static int skl_link_pcm_trigger(struct 
  {
        struct hdac_ext_stream *link_dev =
                                snd_soc_dai_get_dma_data(dai, substream);
 +      struct hdac_ext_bus *ebus = get_bus_ctx(substream);
 +      struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
  
        dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
        switch (cmd) {
 +      case SNDRV_PCM_TRIGGER_RESUME:
 +              skl_link_pcm_prepare(substream, dai);
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 -      case SNDRV_PCM_TRIGGER_RESUME:
 +              snd_hdac_ext_stream_decouple(ebus, stream, true);
                snd_hdac_ext_link_stream_start(link_dev);
                break;
  
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
                snd_hdac_ext_link_stream_clear(link_dev);
 +              if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
 +                      snd_hdac_ext_stream_decouple(ebus, stream, false);
                break;
  
        default:
@@@ -863,6 -829,7 +863,7 @@@ static int skl_get_delay_from_lpib(stru
                else
                        delay += hstream->bufsize;
        }
+       delay = (hstream->bufsize == delay) ? 0 : delay;
  
        if (delay >= hstream->period_bytes) {
                dev_info(bus->dev,
index 4624556f486de34c396a327a0d279a57a1fdbf96,489848637df5b38d5b1c7c428512149e4d9589ae..a294fee431f07363f965a81b4c9ef42eb3a42f58
@@@ -54,12 -54,9 +54,9 @@@ static int is_skl_dsp_widget_type(struc
  
  /*
   * Each pipelines needs memory to be allocated. Check if we have free memory
-  * from available pool. Then only add this to pool
-  * This is freed when pipe is deleted
-  * Note: DSP does actual memory management we only keep track for complete
-  * pool
+  * from available pool.
   */
- static bool skl_tplg_alloc_pipe_mem(struct skl *skl,
+ static bool skl_is_pipe_mem_avail(struct skl *skl,
                                struct skl_module_cfg *mconfig)
  {
        struct skl_sst *ctx = skl->skl_sst;
                                "exceeds ppl memory available %d mem %d\n",
                                skl->resource.max_mem, skl->resource.mem);
                return false;
+       } else {
+               return true;
        }
+ }
  
+ /*
+  * Add the mem to the mem pool. This is freed when pipe is deleted.
+  * Note: DSP does actual memory management we only keep track for complete
+  * pool
+  */
+ static void skl_tplg_alloc_pipe_mem(struct skl *skl,
+                               struct skl_module_cfg *mconfig)
+ {
        skl->resource.mem += mconfig->pipe->memory_pages;
-       return true;
  }
  
  /*
   * quantified in MCPS (Million Clocks Per Second) required for module/pipe
   *
   * Each pipelines needs mcps to be allocated. Check if we have mcps for this
-  * pipe. This adds the mcps to driver counter
-  * This is removed on pipeline delete
+  * pipe.
   */
- static bool skl_tplg_alloc_pipe_mcps(struct skl *skl,
+ static bool skl_is_pipe_mcps_avail(struct skl *skl,
                                struct skl_module_cfg *mconfig)
  {
        struct skl_sst *ctx = skl->skl_sst;
                        "%s: module_id %d instance %d\n", __func__,
                        mconfig->id.module_id, mconfig->id.instance_id);
                dev_err(ctx->dev,
-                       "exceeds ppl memory available %d > mem %d\n",
+                       "exceeds ppl mcps available %d > mem %d\n",
                        skl->resource.max_mcps, skl->resource.mcps);
                return false;
+       } else {
+               return true;
        }
+ }
  
+ static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
+                               struct skl_module_cfg *mconfig)
+ {
        skl->resource.mcps += mconfig->mcps;
-       return true;
  }
  
  /*
@@@ -411,7 -423,7 +423,7 @@@ skl_tplg_init_pipe_modules(struct skl *
                mconfig = w->priv;
  
                /* check resource available */
-               if (!skl_tplg_alloc_pipe_mcps(skl, mconfig))
+               if (!skl_is_pipe_mcps_avail(skl, mconfig))
                        return -ENOMEM;
  
                if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
                ret = skl_tplg_set_module_params(w, ctx);
                if (ret < 0)
                        return ret;
+               skl_tplg_alloc_pipe_mcps(skl, mconfig);
        }
  
        return 0;
@@@ -477,10 -490,10 +490,10 @@@ static int skl_tplg_mixer_dapm_pre_pmu_
        struct skl_sst *ctx = skl->skl_sst;
  
        /* check resource available */
-       if (!skl_tplg_alloc_pipe_mcps(skl, mconfig))
+       if (!skl_is_pipe_mcps_avail(skl, mconfig))
                return -EBUSY;
  
-       if (!skl_tplg_alloc_pipe_mem(skl, mconfig))
+       if (!skl_is_pipe_mem_avail(skl, mconfig))
                return -ENOMEM;
  
        /*
                src_module = dst_module;
        }
  
+       skl_tplg_alloc_pipe_mem(skl, mconfig);
+       skl_tplg_alloc_pipe_mcps(skl, mconfig);
        return 0;
  }
  
  static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
                                struct skl *skl,
+                               struct snd_soc_dapm_widget *src_w,
                                struct skl_module_cfg *src_mconfig)
  {
        struct snd_soc_dapm_path *p;
                dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
  
                next_sink = p->sink;
+               if (!is_skl_dsp_widget_type(p->sink))
+                       return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig);
                /*
                 * here we will check widgets in sink pipelines, so that
                 * can be any widgets type and we are only interested if
        }
  
        if (!sink)
-               return skl_tplg_bind_sinks(next_sink, skl, src_mconfig);
+               return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig);
  
        return 0;
  }
@@@ -605,7 -626,7 +626,7 @@@ static int skl_tplg_pga_dapm_pre_pmu_ev
         * if sink is not started, start sink pipe first, then start
         * this pipe
         */
-       ret = skl_tplg_bind_sinks(w, skl, src_mconfig);
+       ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig);
        if (ret)
                return ret;
  
@@@ -773,10 -794,7 +794,7 @@@ static int skl_tplg_mixer_dapm_post_pmd
                        continue;
                }
  
-               ret = skl_unbind_modules(ctx, src_module, dst_module);
-               if (ret < 0)
-                       return ret;
+               skl_unbind_modules(ctx, src_module, dst_module);
                src_module = dst_module;
        }
  
@@@ -814,9 -832,6 +832,6 @@@ static int skl_tplg_pga_dapm_post_pmd_e
                         * This is a connecter and if path is found that means
                         * unbind between source and sink has not happened yet
                         */
-                       ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
-                       if (ret < 0)
-                               return ret;
                        ret = skl_unbind_modules(ctx, src_mconfig,
                                                        sink_mconfig);
                }
@@@ -842,6 -857,12 +857,12 @@@ static int skl_tplg_vmixer_event(struc
        case SND_SOC_DAPM_PRE_PMU:
                return skl_tplg_mixer_dapm_pre_pmu_event(w, skl);
  
+       case SND_SOC_DAPM_POST_PMU:
+               return skl_tplg_mixer_dapm_post_pmu_event(w, skl);
+       case SND_SOC_DAPM_PRE_PMD:
+               return skl_tplg_mixer_dapm_pre_pmd_event(w, skl);
        case SND_SOC_DAPM_POST_PMD:
                return skl_tplg_mixer_dapm_post_pmd_event(w, skl);
        }
@@@ -916,6 -937,13 +937,13 @@@ static int skl_tplg_tlv_control_get(str
                skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
                                      bc->max, bc->param_id, mconfig);
  
+       /* decrement size for TLV header */
+       size -= 2 * sizeof(u32);
+       /* check size as we don't want to send kernel data */
+       if (size > bc->max)
+               size = bc->max;
        if (bc->params) {
                if (copy_to_user(data, &bc->param_id, sizeof(u32)))
                        return -EFAULT;
@@@ -1508,15 -1536,15 +1536,16 @@@ int skl_tplg_init(struct snd_soc_platfo
         */
        ret = snd_soc_tplg_component_load(&platform->component,
                                        &skl_tplg_ops, fw, 0);
 -      release_firmware(fw);
        if (ret < 0) {
                dev_err(bus->dev, "tplg component load failed%d\n", ret);
+               release_firmware(fw);
                return -EINVAL;
        }
  
        skl->resource.max_mcps = SKL_MAX_MCPS;
        skl->resource.max_mem = SKL_FW_MAX_MEM;
  
 +      skl->tplg = fw;
 +
        return 0;
  }
index 443a15de94b5fbc3813f126da74e4bb3781f6e15,1d36b28d64895eb682d9549a79c228ad3db4fb2d..092705e73db497fb1d75c1c9b45a3c2aaaa34507
  #include <linux/pci.h>
  #include <linux/pm_runtime.h>
  #include <linux/platform_device.h>
 +#include <linux/firmware.h>
  #include <sound/pcm.h>
  #include "../common/sst-acpi.h"
  #include "skl.h"
 +#include "skl-sst-dsp.h"
 +#include "skl-sst-ipc.h"
  
  /*
   * initialize the PCI registers
@@@ -61,49 -58,6 +61,49 @@@ static void skl_init_pci(struct skl *sk
        skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0);
  }
  
 +static void update_pci_dword(struct pci_dev *pci,
 +                      unsigned int reg, u32 mask, u32 val)
 +{
 +      u32 data = 0;
 +
 +      pci_read_config_dword(pci, reg, &data);
 +      data &= ~mask;
 +      data |= (val & mask);
 +      pci_write_config_dword(pci, reg, data);
 +}
 +
 +/*
 + * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits
 + *
 + * @dev: device pointer
 + * @enable: enable/disable flag
 + */
 +static void skl_enable_miscbdcge(struct device *dev, bool enable)
 +{
 +      struct pci_dev *pci = to_pci_dev(dev);
 +      u32 val;
 +
 +      val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0;
 +
 +      update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val);
 +}
 +
 +/*
 + * While performing reset, controller may not come back properly causing
 + * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
 + * (init chip) and then again set CGCTL.MISCBDCGE to 1
 + */
 +static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
 +{
 +      int ret;
 +
 +      skl_enable_miscbdcge(bus->dev, false);
 +      ret = snd_hdac_bus_init_chip(bus, full_reset);
 +      skl_enable_miscbdcge(bus->dev, true);
 +
 +      return ret;
 +}
 +
  /* called from IRQ */
  static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr)
  {
@@@ -190,9 -144,7 +190,9 @@@ static int _skl_suspend(struct hdac_ext
                return ret;
  
        snd_hdac_bus_stop_chip(bus);
 +      skl_enable_miscbdcge(bus->dev, false);
        snd_hdac_bus_enter_link_reset(bus);
 +      skl_enable_miscbdcge(bus->dev, true);
  
        return 0;
  }
@@@ -203,7 -155,7 +203,7 @@@ static int _skl_resume(struct hdac_ext_
        struct hdac_bus *bus = ebus_to_hbus(ebus);
  
        skl_init_pci(skl);
 -      snd_hdac_bus_init_chip(bus, true);
 +      skl_init_chip(bus, true);
  
        return skl_resume_dsp(skl);
  }
@@@ -218,15 -170,12 +218,15 @@@ static int skl_suspend(struct device *d
        struct pci_dev *pci = to_pci_dev(dev);
        struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
        struct skl *skl  = ebus_to_skl(ebus);
 +      struct hdac_bus *bus = ebus_to_hbus(ebus);
  
        /*
         * Do not suspend if streams which are marked ignore suspend are
         * running, we need to save the state for these and continue
         */
        if (skl->supend_active) {
 +              snd_hdac_ext_bus_link_power_down_all(ebus);
 +              enable_irq_wake(bus->irq);
                pci_save_state(pci);
                pci_disable_device(pci);
                return 0;
@@@ -240,7 -189,6 +240,7 @@@ static int skl_resume(struct device *de
        struct pci_dev *pci = to_pci_dev(dev);
        struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
        struct skl *skl  = ebus_to_skl(ebus);
 +      struct hdac_bus *bus = ebus_to_hbus(ebus);
        int ret;
  
        /*
        if (skl->supend_active) {
                pci_restore_state(pci);
                ret = pci_enable_device(pci);
 +              snd_hdac_ext_bus_link_power_up_all(ebus);
 +              disable_irq_wake(bus->irq);
        } else {
                ret = _skl_resume(ebus);
        }
@@@ -433,7 -379,7 +433,7 @@@ static int skl_codec_create(struct hdac
                                 * back to the sanity state.
                                 */
                                snd_hdac_bus_stop_chip(bus);
 -                              snd_hdac_bus_init_chip(bus, true);
 +                              skl_init_chip(bus, true);
                        }
                }
        }
@@@ -543,7 -489,7 +543,7 @@@ static int skl_first_init(struct hdac_e
        /* initialize chip */
        skl_init_pci(skl);
  
 -      snd_hdac_bus_init_chip(bus, true);
 +      skl_init_chip(bus, true);
  
        /* codec detection */
        if (!bus->codec_mask) {
@@@ -592,8 -538,6 +592,8 @@@ static int skl_probe(struct pci_dev *pc
                        dev_dbg(bus->dev, "error failed to register dsp\n");
                        goto out_mach_free;
                }
 +              skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
 +
        }
        if (ebus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(ebus);
                goto out_unregister;
  
        /*configure PM */
-       pm_runtime_set_autosuspend_delay(bus->dev, SKL_SUSPEND_DELAY);
-       pm_runtime_use_autosuspend(bus->dev);
        pm_runtime_put_noidle(bus->dev);
        pm_runtime_allow(bus->dev);
  
@@@ -641,9 -583,6 +639,9 @@@ static void skl_remove(struct pci_dev *
        struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
        struct skl *skl = ebus_to_skl(ebus);
  
 +      if (skl->tplg)
 +              release_firmware(skl->tplg);
 +
        if (pci_dev_run_wake(pci))
                pm_runtime_get_noresume(&pci->dev);
        pci_dev_put(pci);
This page took 0.038492 seconds and 5 git commands to generate.