Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
authorMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:51:30 +0000 (16:51 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:51:30 +0000 (16:51 +0100)
1  2 
sound/soc/codecs/rt5670.c
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/soc-core.c

index d95d2e693dc6c9cf380f2d6ab2341df7f4d66b89,d90c74ef5c4271d6b49c94090e8069a8209a991a..a5f15a104c47a7558405380f8603490e7bd9b921
@@@ -1717,6 -1717,7 +1717,6 @@@ static const struct snd_soc_dapm_widge
        SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
 -      SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
  
        /* DSP */
        SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
@@@ -2085,13 -2086,13 +2085,13 @@@ static const struct snd_soc_dapm_route 
        { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" },
  
        { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" },
 -      { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" },
 +      { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "TxDP_ADC" },
  
        { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" },
        { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" },
  
        { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" },
 -      { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" },
 +      { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "TxDP_ADC" },
  
        { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" },
        { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" },
@@@ -2848,6 -2849,10 +2848,10 @@@ static const struct dmi_system_id dmi_p
                        DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"),
                },
        },
+       {}
+ };
+ static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = {
        {
                .ident = "Lenovo Thinkpad Tablet 10",
                .matches = {
@@@ -2882,6 -2887,11 +2886,11 @@@ static int rt5670_i2c_probe(struct i2c_
                rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
                rt5670->pdata.dev_gpio = true;
                rt5670->pdata.jd_mode = 1;
+       } else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode2)) {
+               rt5670->pdata.dmic_en = true;
+               rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
+               rt5670->pdata.dev_gpio = true;
+               rt5670->pdata.jd_mode = 2;
        }
  
        rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
index 1866e31b6c29e9912d13d173856eb34456fba06b,1429eb391da857e109a17d4fb3ecc0a3f4671a52..ce35ec7884d1e59873e184d3dd8f5bf0711806a6
@@@ -89,6 -89,11 +89,6 @@@ static int platform_clock_control(struc
                if (ret)
                        dev_err(card->dev, "failed to stop PLL: %d\n", ret);
        } else if(SND_SOC_DAPM_EVENT_ON(event)) {
 -              ret = snd_soc_dai_set_sysclk(codec_dai,
 -                        DA7219_CLKSRC_MCLK, 19200000, SND_SOC_CLOCK_IN);
 -              if (ret)
 -                      dev_err(card->dev, "can't set codec sysclk configuration\n");
 -
                ret = snd_soc_dai_set_pll(codec_dai, 0,
                        DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304);
                if (ret)
@@@ -182,17 -187,8 +182,17 @@@ static int broxton_ssp_fixup(struct snd
  static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
  {
        int ret;
 +      struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_codec *codec = rtd->codec;
  
 +      /* Configure sysclk for codec */
 +      ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 19200000,
 +                                   SND_SOC_CLOCK_IN);
 +      if (ret) {
 +              dev_err(rtd->dev, "can't set codec sysclk configuration\n");
 +              return ret;
 +      }
 +
        /*
         * Headset buttons map to the google Reference headset.
         * These can be configured by userspace.
@@@ -242,31 -238,31 +242,31 @@@ static int broxton_da7219_fe_init(struc
        return 0;
  }
  
- static unsigned int rates[] = {
+ static const unsigned int rates[] = {
        48000,
  };
  
- static struct snd_pcm_hw_constraint_list constraints_rates = {
+ static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
  };
  
- static unsigned int channels[] = {
+ static const unsigned int channels[] = {
        DUAL_CHANNEL,
  };
  
- static struct snd_pcm_hw_constraint_list constraints_channels = {
+ static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
  };
  
- static unsigned int channels_quad[] = {
+ static const unsigned int channels_quad[] = {
        QUAD_CHANNEL,
  };
  
- static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
+ static const struct snd_pcm_hw_constraint_list constraints_channels_quad = {
        .count = ARRAY_SIZE(channels_quad),
        .list = channels_quad,
        .mask = 0,
index 64a0f8ed33e135eb5c0af683624afa3ebdb616b9,c02da16fdfd61c9a43ac5f5836ebf1c18f5a9f17..68c3f121efc3b22a4caff235303be07ba9914721
  #define SKL_IN_DIR_BIT_MASK           BIT(0)
  #define SKL_PIN_COUNT_MASK            GENMASK(7, 4)
  
+ static const int mic_mono_list[] = {
+ 0, 1, 2, 3,
+ };
+ static const int mic_stereo_list[][SKL_CH_STEREO] = {
+ {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
+ };
+ static const int mic_trio_list[][SKL_CH_TRIO] = {
+ {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3},
+ };
+ static const int mic_quatro_list[][SKL_CH_QUATRO] = {
+ {0, 1, 2, 3},
+ };
  void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
  {
        struct skl_d0i3_data *d0i3 =  &skl->skl_sst->d0i3;
@@@ -1314,6 -1327,111 +1327,111 @@@ static int skl_tplg_tlv_control_set(str
        return 0;
  }
  
+ static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+ {
+       struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+       struct skl_module_cfg *mconfig = w->priv;
+       struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+       u32 ch_type = *((u32 *)ec->dobj.private);
+       if (mconfig->dmic_ch_type == ch_type)
+               ucontrol->value.enumerated.item[0] =
+                                       mconfig->dmic_ch_combo_index;
+       else
+               ucontrol->value.enumerated.item[0] = 0;
+       return 0;
+ }
+ static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
+       struct skl_mic_sel_config *mic_cfg, struct device *dev)
+ {
+       struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
+       sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
+       sp_cfg->set_params = SKL_PARAM_SET;
+       sp_cfg->param_id = 0x00;
+       if (!sp_cfg->caps) {
+               sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL);
+               if (!sp_cfg->caps)
+                       return -ENOMEM;
+       }
+       mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH;
+       mic_cfg->flags = 0;
+       memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size);
+       return 0;
+ }
+ static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+ {
+       struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+       struct skl_module_cfg *mconfig = w->priv;
+       struct skl_mic_sel_config mic_cfg = {0};
+       struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+       u32 ch_type = *((u32 *)ec->dobj.private);
+       const int *list;
+       u8 in_ch, out_ch, index;
+       mconfig->dmic_ch_type = ch_type;
+       mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0];
+       /* enum control index 0 is INVALID, so no channels to be set */
+       if (mconfig->dmic_ch_combo_index == 0)
+               return 0;
+       /* No valid channel selection map for index 0, so offset by 1 */
+       index = mconfig->dmic_ch_combo_index - 1;
+       switch (ch_type) {
+       case SKL_CH_MONO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list))
+                       return -EINVAL;
+               list = &mic_mono_list[index];
+               break;
+       case SKL_CH_STEREO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list))
+                       return -EINVAL;
+               list = mic_stereo_list[index];
+               break;
+       case SKL_CH_TRIO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list))
+                       return -EINVAL;
+               list = mic_trio_list[index];
+               break;
+       case SKL_CH_QUATRO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list))
+                       return -EINVAL;
+               list = mic_quatro_list[index];
+               break;
+       default:
+               dev_err(w->dapm->dev,
+                               "Invalid channel %d for mic_select module\n",
+                               ch_type);
+               return -EINVAL;
+       }
+       /* channel type enum map to number of chanels for that type */
+       for (out_ch = 0; out_ch < ch_type; out_ch++) {
+               in_ch = list[out_ch];
+               mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN;
+       }
+       return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev);
+ }
  /*
   * Fill the dma id for host and link. In case of passthrough
   * pipeline, this will both host and link in the same
@@@ -1666,6 -1784,14 +1784,14 @@@ static const struct snd_soc_tplg_bytes_
                                        skl_tplg_tlv_control_set},
  };
  
+ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
+       {
+               .id = SKL_CONTROL_TYPE_MIC_SELECT,
+               .get = skl_tplg_mic_control_get,
+               .put = skl_tplg_mic_control_set,
+       },
+ };
  static int skl_tplg_fill_pipe_tkn(struct device *dev,
                        struct skl_pipe *pipe, u32 tkn,
                        u32 tkn_val)
@@@ -1995,7 -2121,7 +2121,7 @@@ static int skl_tplg_get_token(struct de
                mconfig->converter = tkn_elem->value;
                break;
  
-       case SKL_TKL_U32_D0I3_CAPS:
+       case SKL_TKN_U32_D0I3_CAPS:
                mconfig->d0i3_caps = tkn_elem->value;
                break;
  
  
                break;
  
+       case SKL_TKN_U32_CAPS_SET_PARAMS:
+               mconfig->formats_config.set_params =
+                               tkn_elem->value;
+               break;
+       case SKL_TKN_U32_CAPS_PARAMS_ID:
+               mconfig->formats_config.param_id =
+                               tkn_elem->value;
+               break;
        case SKL_TKN_U32_PROC_DOMAIN:
                mconfig->domain =
                        tkn_elem->value;
  
                break;
  
+       case SKL_TKN_U32_DMA_BUF_SIZE:
+               mconfig->dma_buffer_size = tkn_elem->value;
+               break;
        case SKL_TKN_U8_IN_PIN_TYPE:
        case SKL_TKN_U8_OUT_PIN_TYPE:
        case SKL_TKN_U8_CONN_TYPE:
@@@ -2147,7 -2287,7 +2287,7 @@@ static int skl_tplg_get_tokens(struct d
                tuple_size += tkn_count * sizeof(*tkn_elem);
        }
  
-       return 0;
+       return off;
  }
  
  /*
@@@ -2198,10 -2338,11 +2338,11 @@@ static int skl_tplg_get_pvt_data(struc
        num_blocks = ret;
  
        off += array->size;
-       array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off);
        /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
        while (num_blocks > 0) {
+               array = (struct snd_soc_tplg_vendor_array *)
+                               (tplg_w->priv.data + off);
                ret = skl_tplg_get_desc_blocks(dev, array);
  
                if (ret < 0)
                                memcpy(mconfig->formats_config.caps, data,
                                        mconfig->formats_config.caps_size);
                        --num_blocks;
+                       ret = mconfig->formats_config.caps_size;
                }
+               off += ret;
        }
  
        return 0;
@@@ -2329,6 -2472,9 +2472,9 @@@ static int skl_tplg_widget_load(struct 
        ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
        if (ret < 0)
                return ret;
+       skl_debug_init_module(skl->debugfs, w, mconfig);
  bind_event:
        if (tplg_w->event_type == 0) {
                dev_dbg(bus->dev, "ASoC: No event handler required\n");
@@@ -2377,14 -2523,34 +2523,34 @@@ static int skl_init_algo_data(struct de
        return 0;
  }
  
+ static int skl_init_enum_data(struct device *dev, struct soc_enum *se,
+                               struct snd_soc_tplg_enum_control *ec)
+ {
+       void *data;
+       if (ec->priv.size) {
+               data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+               memcpy(data, ec->priv.data, ec->priv.size);
+               se->dobj.private = data;
+       }
+       return 0;
+ }
  static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
                                struct snd_kcontrol_new *kctl,
                                struct snd_soc_tplg_ctl_hdr *hdr)
  {
        struct soc_bytes_ext *sb;
        struct snd_soc_tplg_bytes_control *tplg_bc;
+       struct snd_soc_tplg_enum_control *tplg_ec;
        struct hdac_ext_bus *ebus  = snd_soc_component_get_drvdata(cmpnt);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct soc_enum *se;
  
        switch (hdr->ops.info) {
        case SND_SOC_TPLG_CTL_BYTES:
                }
                break;
  
+       case SND_SOC_TPLG_CTL_ENUM:
+               tplg_ec = container_of(hdr,
+                               struct snd_soc_tplg_enum_control, hdr);
+               if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
+                       se = (struct soc_enum *)kctl->private_value;
+                       if (tplg_ec->priv.size)
+                               return skl_init_enum_data(bus->dev, se,
+                                               tplg_ec);
+               }
+               break;
        default:
                dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
                        hdr->ops.get, hdr->ops.put, hdr->ops.info);
@@@ -2502,7 -2679,7 +2679,7 @@@ static int skl_tplg_get_manifest_tkn(st
  
                        if (ret < 0)
                                return ret;
 -                      tkn_count += ret;
 +                      tkn_count = ret;
  
                        tuple_size += tkn_count *
                                sizeof(struct snd_soc_tplg_vendor_string_elem);
@@@ -2626,6 -2803,8 +2803,8 @@@ static struct snd_soc_tplg_ops skl_tplg
        .control_load = skl_tplg_control_load,
        .bytes_ext_ops = skl_tlv_ops,
        .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
+       .io_ops = skl_tplg_kcontrol_ops,
+       .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
        .manifest = skl_manifest_load,
  };
  
diff --combined sound/soc/soc-core.c
index 754e3ef8d7ae1b8b188c3e52986f2c306fb7b763,6bd593dc9b549a3b4758081ee74e555501f4fd8b..180bfbfe833da3c53a32a1845392d2af554e3929
@@@ -68,6 -68,20 +68,20 @@@ static int pmdown_time = 5000
  module_param(pmdown_time, int, 0);
  MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
  
+ /* If a DMI filed contain strings in this blacklist (e.g.
+  * "Type2 - Board Manufacturer" or  "Type1 - TBD by OEM"), it will be taken
+  * as invalid and dropped when setting the card long name from DMI info.
+  */
+ static const char * const dmi_blacklist[] = {
+       "To be filled by OEM",
+       "TBD by OEM",
+       "Default String",
+       "Board Manufacturer",
+       "Board Vendor Name",
+       "Board Product Name",
+       NULL,   /* terminator */
+ };
  /* returns the minimum number of bytes needed to represent
   * a particular given value */
  static int min_bytes_needed(unsigned long val)
@@@ -1933,6 -1947,22 +1947,22 @@@ static void cleanup_dmi_name(char *name
        name[j] = '\0';
  }
  
+ /* Check if a DMI field is valid, i.e. not containing any string
+  * in the black list.
+  */
+ static int is_dmi_valid(const char *field)
+ {
+       int i = 0;
+       while (dmi_blacklist[i]) {
+               if (strstr(field, dmi_blacklist[i]))
+                       return 0;
+               i++;
+       }
+       return 1;
+ }
  /**
   * snd_soc_set_dmi_name() - Register DMI names to card
   * @card: The card to register DMI names
@@@ -1975,17 -2005,18 +2005,18 @@@ int snd_soc_set_dmi_name(struct snd_soc
  
        /* make up dmi long name as: vendor.product.version.board */
        vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
-       if (!vendor) {
+       if (!vendor || !is_dmi_valid(vendor)) {
                dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
                return 0;
        }
  
        snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
                         "%s", vendor);
        cleanup_dmi_name(card->dmi_longname);
  
        product = dmi_get_system_info(DMI_PRODUCT_NAME);
-       if (product) {
+       if (product && is_dmi_valid(product)) {
                len = strlen(card->dmi_longname);
                snprintf(card->dmi_longname + len,
                         longname_buf_size - len,
                 * name in the product version field
                 */
                product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
-               if (product_version) {
+               if (product_version && is_dmi_valid(product_version)) {
                        len = strlen(card->dmi_longname);
                        snprintf(card->dmi_longname + len,
                                 longname_buf_size - len,
        }
  
        board = dmi_get_system_info(DMI_BOARD_NAME);
-       if (board) {
+       if (board && is_dmi_valid(board)) {
                len = strlen(card->dmi_longname);
                snprintf(card->dmi_longname + len,
                         longname_buf_size - len,
@@@ -2286,9 -2317,6 +2317,9 @@@ static int soc_cleanup_card_resources(s
        list_for_each_entry(rtd, &card->rtd_list, list)
                flush_delayed_work(&rtd->delayed_work);
  
 +      /* free the ALSA card at first; this syncs with pending operations */
 +      snd_card_free(card->snd_card);
 +
        /* remove and free each DAI */
        soc_remove_dai_links(card);
        soc_remove_pcm_runtimes(card);
        if (card->remove)
                card->remove(card);
  
 -      snd_card_free(card->snd_card);
        return 0;
 -
  }
  
  /* removes a socdev */