Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
authorMark Brown <broonie@kernel.org>
Sun, 13 Mar 2016 08:16:26 +0000 (15:16 +0700)
committerMark Brown <broonie@kernel.org>
Sun, 13 Mar 2016 08:16:26 +0000 (15:16 +0700)
1  2 
sound/soc/intel/Kconfig
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/common/sst-match-acpi.c
sound/soc/intel/skylake/skl-topology.c

diff --combined sound/soc/intel/Kconfig
@@@ -30,15 -30,11 +30,15 @@@ config SND_SST_IPC_ACP
  config SND_SOC_INTEL_SST
        tristate
        select SND_SOC_INTEL_SST_ACPI if ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
        depends on (X86 || COMPILE_TEST)
  
  config SND_SOC_INTEL_SST_ACPI
        tristate
  
 +config SND_SOC_INTEL_SST_MATCH
 +      tristate
 +
  config SND_SOC_INTEL_HASWELL
        tristate
  
@@@ -61,7 -57,7 +61,7 @@@ config SND_SOC_INTEL_HASWELL_MAC
  config SND_SOC_INTEL_BYT_RT5640_MACH
        tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
        depends on X86_INTEL_LPSS && I2C
 -      depends on DW_DMAC_CORE=y && (SND_SOC_INTEL_BYTCR_RT5640_MACH = n)
 +      depends on DW_DMAC_CORE=y && (SND_SST_IPC_ACPI = n)
        select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_BAYTRAIL
        select SND_SOC_RT5640
@@@ -73,7 -69,7 +73,7 @@@
  config SND_SOC_INTEL_BYT_MAX98090_MACH
        tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
        depends on X86_INTEL_LPSS && I2C
 -      depends on DW_DMAC_CORE=y
 +      depends on DW_DMAC_CORE=y && (SND_SST_IPC_ACPI = n)
        select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_BAYTRAIL
        select SND_SOC_MAX98090
@@@ -101,7 -97,6 +101,7 @@@ config SND_SOC_INTEL_BYTCR_RT5640_MAC
        select SND_SOC_RT5640
        select SND_SST_MFLD_PLATFORM
        select SND_SST_IPC_ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
        help
            This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
            platforms with RT5640 audio codec.
@@@ -114,7 -109,6 +114,7 @@@ config SND_SOC_INTEL_BYTCR_RT5651_MAC
        select SND_SOC_RT5651
        select SND_SST_MFLD_PLATFORM
        select SND_SST_IPC_ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
        help
            This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
            platforms with RT5651 audio codec.
@@@ -127,7 -121,6 +127,7 @@@ config SND_SOC_INTEL_CHT_BSW_RT5672_MAC
          select SND_SOC_RT5670
          select SND_SST_MFLD_PLATFORM
          select SND_SST_IPC_ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
          help
            This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
            platforms with RT5672 audio codec.
@@@ -140,7 -133,6 +140,7 @@@ config SND_SOC_INTEL_CHT_BSW_RT5645_MAC
        select SND_SOC_RT5645
        select SND_SST_MFLD_PLATFORM
        select SND_SST_IPC_ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
        help
          This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
          platforms with RT5645/5650 audio codec.
@@@ -153,7 -145,6 +153,7 @@@ config SND_SOC_INTEL_CHT_BSW_MAX98090_T
        select SND_SOC_TS3A227E
        select SND_SST_MFLD_PLATFORM
        select SND_SST_IPC_ACPI
 +      select SND_SOC_INTEL_SST_MATCH if ACPI
        help
        This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
        platforms with MAX98090 audio codec it also can support TI jack chip as aux device.
@@@ -163,6 -154,7 +163,7 @@@ config SND_SOC_INTEL_SKYLAK
        tristate
        select SND_HDA_EXT_CORE
        select SND_SOC_TOPOLOGY
+       select SND_HDA_I915
        select SND_SOC_INTEL_SST
  
  config SND_SOC_INTEL_SKL_RT286_MACH
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_RT286
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
           This adds support for ASoC machine driver for Skylake platforms
           with RT286 I2S audio codec.
@@@ -186,6 -179,7 +188,7 @@@ config SND_SOC_INTEL_SKL_NAU88L25_SSM45
        select SND_SOC_NAU8825
        select SND_SOC_SSM4567
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
          This adds support for ASoC Onboard Codec I2S machine driver. This will
          create an alsa sound card for NAU88L25 + SSM4567.
@@@ -200,6 -194,7 +203,7 @@@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98
        select SND_SOC_NAU8825
        select SND_SOC_MAX98357A
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
          This adds support for ASoC Onboard Codec I2S machine driver. This will
          create an alsa sound card for NAU88L25 + MAX98357A.
@@@ -147,6 -147,17 +147,17 @@@ static const struct snd_kcontrol_new ch
        SOC_DAPM_PIN_SWITCH("Ext Spk"),
  };
  
+ static struct snd_soc_jack_pin cht_bsw_jack_pins[] = {
+       {
+               .pin    = "Headphone",
+               .mask   = SND_JACK_HEADPHONE,
+       },
+       {
+               .pin    = "Headset Mic",
+               .mask   = SND_JACK_MICROPHONE,
+       },
+ };
  static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
  {
@@@ -202,9 -213,9 +213,9 @@@ static int cht_codec_init(struct snd_so
        else
                jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE;
  
-       ret = snd_soc_card_jack_new(runtime->card, "Headset Jack",
+       ret = snd_soc_card_jack_new(runtime->card, "Headset",
                                    jack_type, &ctx->jack,
-                                   NULL, 0);
+                                   cht_bsw_jack_pins, ARRAY_SIZE(cht_bsw_jack_pins));
        if (ret) {
                dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
                return ret;
@@@ -333,20 -344,12 +344,12 @@@ static struct cht_acpi_card snd_soc_car
        {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
  };
  
- static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level,
-                                      void *context, void **ret)
- {
-       *(bool *)context = true;
-       return AE_OK;
- }
  static int snd_cht_mc_probe(struct platform_device *pdev)
  {
        int ret_val = 0;
        int i;
        struct cht_mc_private *drv;
        struct snd_soc_card *card = snd_soc_cards[0].soc_card;
-       bool found = false;
        char codec_name[16];
  
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
                return -ENOMEM;
  
        for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
-               if (ACPI_SUCCESS(acpi_get_devices(
-                                               snd_soc_cards[i].codec_id,
-                                               snd_acpi_codec_match,
-                                               &found, NULL)) && found) {
+               if (acpi_dev_present(snd_soc_cards[i].codec_id)) {
                        dev_dbg(&pdev->dev,
                                "found codec %s\n", snd_soc_cards[i].codec_id);
                        card = snd_soc_cards[i].soc_card;
        }
        card->dev = &pdev->dev;
        sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
 +
        /* set correct codec name */
 -      strcpy((char *)card->dai_link[2].codec_name, codec_name);
 +      for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
 +              if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00"))
 +                      card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL);
 +
        snd_soc_card_set_drvdata(card, drv);
        ret_val = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret_val) {
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   */
- #include <linux/acpi.h>
- #include <linux/device.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
  
  #include "sst-acpi.h"
  
+ static acpi_status sst_acpi_find_name(acpi_handle handle, u32 level,
+                                     void *context, void **ret)
+ {
+       struct acpi_device *adev;
+       const char *name = NULL;
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+       if (adev->status.present && adev->status.functional) {
+               name = acpi_dev_name(adev);
+               *(const char **)ret = name;
+               return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+ }
+ const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
+ {
+       const char *name = NULL;
+       acpi_status status;
+       status = acpi_get_devices(hid, sst_acpi_find_name, NULL,
+                                 (void **)&name);
+       if (ACPI_FAILURE(status) || name[0] == '\0')
+               return NULL;
+       return name;
+ }
+ EXPORT_SYMBOL_GPL(sst_acpi_find_name_from_hid);
  static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
                                       void *context, void **ret)
  {
+       unsigned long long sta;
+       acpi_status status;
        *(bool *)context = true;
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
+               *(bool *)context = false;
        return AE_OK;
  }
  
@@@ -37,10 -73,6 +73,9 @@@ struct sst_acpi_mach *sst_acpi_find_mac
                                                  sst_acpi_mach_match,
                                                  &found, NULL)) && found)
                        return mach;
        return NULL;
  }
  EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
 +
 +MODULE_LICENSE("GPL v2");
 +MODULE_DESCRIPTION("Intel Common ACPI Match module");
@@@ -260,6 -260,65 +260,65 @@@ static void skl_tplg_update_buffer_size
                                multiplier;
  }
  
+ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
+                                               struct skl_sst *ctx)
+ {
+       struct skl_module_cfg *m_cfg = w->priv;
+       int link_type, dir;
+       u32 ch, s_freq, s_fmt;
+       struct nhlt_specific_cfg *cfg;
+       struct skl *skl = get_skl_ctx(ctx->dev);
+       /* check if we already have blob */
+       if (m_cfg->formats_config.caps_size > 0)
+               return 0;
+       dev_dbg(ctx->dev, "Applying default cfg blob\n");
+       switch (m_cfg->dev_type) {
+       case SKL_DEVICE_DMIC:
+               link_type = NHLT_LINK_DMIC;
+               dir = SNDRV_PCM_STREAM_CAPTURE;
+               s_freq = m_cfg->in_fmt[0].s_freq;
+               s_fmt = m_cfg->in_fmt[0].bit_depth;
+               ch = m_cfg->in_fmt[0].channels;
+               break;
+       case SKL_DEVICE_I2S:
+               link_type = NHLT_LINK_SSP;
+               if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
+                       dir = SNDRV_PCM_STREAM_PLAYBACK;
+                       s_freq = m_cfg->out_fmt[0].s_freq;
+                       s_fmt = m_cfg->out_fmt[0].bit_depth;
+                       ch = m_cfg->out_fmt[0].channels;
+               } else {
+                       dir = SNDRV_PCM_STREAM_CAPTURE;
+                       s_freq = m_cfg->in_fmt[0].s_freq;
+                       s_fmt = m_cfg->in_fmt[0].bit_depth;
+                       ch = m_cfg->in_fmt[0].channels;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* update the blob based on virtual bus_id and default params */
+       cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
+                                       s_fmt, ch, s_freq, dir);
+       if (cfg) {
+               m_cfg->formats_config.caps_size = cfg->size;
+               m_cfg->formats_config.caps = (u32 *) &cfg->caps;
+       } else {
+               dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n",
+                                       m_cfg->vbus_id, link_type, dir);
+               dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n",
+                                       ch, s_freq, s_fmt);
+               return -EIO;
+       }
+       return 0;
+ }
  static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
                                                        struct skl_sst *ctx)
  {
@@@ -433,6 -492,9 +492,9 @@@ skl_tplg_init_pipe_modules(struct skl *
                                return ret;
                }
  
+               /* update blob if blob is null for be with default value */
+               skl_tplg_update_be_blob(w, ctx);
                /*
                 * apply fix/conversion to module params based on
                 * FE/BE params
@@@ -545,6 -607,66 +607,66 @@@ static int skl_tplg_mixer_dapm_pre_pmu_
        return 0;
  }
  
+ /*
+  * Some modules require params to be set after the module is bound to
+  * all pins connected.
+  *
+  * The module provider initializes set_param flag for such modules and we
+  * send params after binding
+  */
+ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
+                       struct skl_module_cfg *mcfg, struct skl_sst *ctx)
+ {
+       int i, ret;
+       struct skl_module_cfg *mconfig = w->priv;
+       const struct snd_kcontrol_new *k;
+       struct soc_bytes_ext *sb;
+       struct skl_algo_data *bc;
+       struct skl_specific_cfg *sp_cfg;
+       /*
+        * check all out/in pins are in bind state.
+        * if so set the module param
+        */
+       for (i = 0; i < mcfg->max_out_queue; i++) {
+               if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
+                       return 0;
+       }
+       for (i = 0; i < mcfg->max_in_queue; i++) {
+               if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
+                       return 0;
+       }
+       if (mconfig->formats_config.caps_size > 0 &&
+               mconfig->formats_config.set_params == SKL_PARAM_BIND) {
+               sp_cfg = &mconfig->formats_config;
+               ret = skl_set_module_params(ctx, sp_cfg->caps,
+                                       sp_cfg->caps_size,
+                                       sp_cfg->param_id, mconfig);
+               if (ret < 0)
+                       return ret;
+       }
+       for (i = 0; i < w->num_kcontrols; i++) {
+               k = &w->kcontrol_news[i];
+               if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+                       sb = (void *) k->private_value;
+                       bc = (struct skl_algo_data *)sb->dobj.private;
+                       if (bc->set_params == SKL_PARAM_BIND) {
+                               ret = skl_set_module_params(ctx,
+                                               (u32 *)bc->params, bc->max,
+                                               bc->param_id, mconfig);
+                               if (ret < 0)
+                                       return ret;
+                       }
+               }
+       }
+       return 0;
+ }
  static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
                                struct skl *skl,
                                struct snd_soc_dapm_widget *src_w,
                        sink = p->sink;
                        sink_mconfig = sink->priv;
  
+                       if (src_mconfig->m_state == SKL_MODULE_UNINIT ||
+                               sink_mconfig->m_state == SKL_MODULE_UNINIT)
+                               continue;
                        /* Bind source to sink, mixin is always source */
                        ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig);
                        if (ret)
                                return ret;
  
+                       /* set module params after bind */
+                       skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx);
+                       skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
                        /* Start sinks pipe first */
                        if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
                                if (sink_mconfig->pipe->conn_type !=
@@@ -714,6 -844,10 +844,10 @@@ static int skl_tplg_mixer_dapm_post_pmu
                if (ret)
                        return ret;
  
+               /* set module params after bind */
+               skl_tplg_set_module_bind_params(source, src_mconfig, ctx);
+               skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
                if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
                        ret = skl_run_pipe(ctx, sink_mconfig->pipe);
        }
@@@ -978,7 -1112,7 +1112,7 @@@ static int skl_tplg_tlv_control_set(str
                                return -EFAULT;
                } else {
                        if (copy_from_user(ac->params,
 -                                         data + 2 * sizeof(u32), size))
 +                                         data + 2, size))
                                return -EFAULT;
                }
  
@@@ -1091,6 -1225,66 +1225,66 @@@ skl_tplg_fe_get_cpr_module(struct snd_s
        return NULL;
  }
  
+ static struct skl_module_cfg *skl_get_mconfig_pb_cpr(
+               struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
+ {
+       struct snd_soc_dapm_path *p;
+       struct skl_module_cfg *mconfig = NULL;
+       snd_soc_dapm_widget_for_each_source_path(w, p) {
+               if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) {
+                       if (p->connect &&
+                                   (p->sink->id == snd_soc_dapm_aif_out) &&
+                                   p->source->priv) {
+                               mconfig = p->source->priv;
+                               return mconfig;
+                       }
+                       mconfig = skl_get_mconfig_pb_cpr(dai, p->source);
+                       if (mconfig)
+                               return mconfig;
+               }
+       }
+       return mconfig;
+ }
+ static struct skl_module_cfg *skl_get_mconfig_cap_cpr(
+               struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
+ {
+       struct snd_soc_dapm_path *p;
+       struct skl_module_cfg *mconfig = NULL;
+       snd_soc_dapm_widget_for_each_sink_path(w, p) {
+               if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) {
+                       if (p->connect &&
+                                   (p->source->id == snd_soc_dapm_aif_in) &&
+                                   p->sink->priv) {
+                               mconfig = p->sink->priv;
+                               return mconfig;
+                       }
+                       mconfig = skl_get_mconfig_cap_cpr(dai, p->sink);
+                       if (mconfig)
+                               return mconfig;
+               }
+       }
+       return mconfig;
+ }
+ struct skl_module_cfg *
+ skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream)
+ {
+       struct snd_soc_dapm_widget *w;
+       struct skl_module_cfg *mconfig;
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               w = dai->playback_widget;
+               mconfig = skl_get_mconfig_pb_cpr(dai, w);
+       } else {
+               w = dai->capture_widget;
+               mconfig = skl_get_mconfig_cap_cpr(dai, w);
+       }
+       return mconfig;
+ }
  static u8 skl_tplg_be_link_type(int dev_type)
  {
        int ret;
@@@ -1464,8 -1658,7 +1658,7 @@@ static int skl_init_algo_data(struct de
                if (!ac->params)
                        return -ENOMEM;
  
-               if (dfw_ac->params)
-                       memcpy(ac->params, dfw_ac->params, ac->max);
+               memcpy(ac->params, dfw_ac->params, ac->max);
        }
  
        be->dobj.private  = ac;
@@@ -1523,11 -1716,16 +1716,16 @@@ int skl_tplg_init(struct snd_soc_platfo
        struct hdac_bus *bus = ebus_to_hbus(ebus);
        struct skl *skl = ebus_to_skl(ebus);
  
-       ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
+       ret = request_firmware(&fw, skl->tplg_name, bus->dev);
        if (ret < 0) {
                dev_err(bus->dev, "tplg fw %s load failed with %d\n",
-                               "dfw_sst.bin", ret);
-               return ret;
+                               skl->tplg_name, ret);
+               ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
+               if (ret < 0) {
+                       dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
+                                       "dfw_sst.bin", ret);
+                       return ret;
+               }
        }
  
        /*