From: Mark Brown Date: Mon, 3 Jul 2017 15:51:30 +0000 (+0100) Subject: Merge remote-tracking branch 'asoc/topic/intel' into asoc-next X-Git-Tag: smb3-security-fixes-for-4.13~60^2~1^2~5 X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fcifs-2.6.git;a=commitdiff_plain;h=2016d5ed401133539779d8a070abbe42fe9cb3da;hp=-c Merge remote-tracking branch 'asoc/topic/intel' into asoc-next --- 2016d5ed401133539779d8a070abbe42fe9cb3da diff --combined sound/soc/codecs/rt5670.c index d95d2e693dc6,d90c74ef5c42..a5f15a104c47 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@@ -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); diff --combined sound/soc/intel/boards/bxt_da7219_max98357a.c index 1866e31b6c29,1429eb391da8..ce35ec7884d1 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@@ -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, diff --combined sound/soc/intel/skylake/skl-topology.c index 64a0f8ed33e1,c02da16fdfd6..68c3f121efc3 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@@ -36,6 -36,19 +36,19 @@@ #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; @@@ -2070,12 -2196,26 +2196,26 @@@ 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) @@@ -2237,7 -2378,9 +2378,9 @@@ 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: @@@ -2398,6 -2564,17 +2564,17 @@@ } 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 754e3ef8d7ae,6bd593dc9b54..180bfbfe833d --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@@ -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, @@@ -1999,7 -2030,7 +2030,7 @@@ * 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, @@@ -2012,7 -2043,7 +2043,7 @@@ } 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); @@@ -2303,7 -2331,9 +2334,7 @@@ if (card->remove) card->remove(card); - snd_card_free(card->snd_card); return 0; - } /* removes a socdev */