Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'asoc-fix-v6.7-rc4' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v6.7

A crop of fixes for v6.7, one core fix for a merge issue and a bunch of
driver specific fixes and new IDs, mostly for x86 platforms.

+286 -107
+14
sound/soc/amd/acp-config.c
··· 111 111 .matches = { 112 112 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), 113 113 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), 114 + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), 115 + }, 116 + }, 117 + {} 118 + }, 119 + }, 120 + { 121 + .flags = FLAG_AMD_LEGACY, 122 + .device = ACP_PCI_DEV_ID, 123 + .dmi_table = (const struct dmi_system_id []) { 124 + { 125 + .matches = { 126 + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), 127 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), 114 128 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1020"), 115 129 }, 116 130 },
+21
sound/soc/amd/yc/acp6x-mach.c
··· 286 286 { 287 287 .driver_data = &acp6x_card, 288 288 .matches = { 289 + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), 290 + DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"), 291 + } 292 + }, 293 + { 294 + .driver_data = &acp6x_card, 295 + .matches = { 289 296 DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), 290 297 DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"), 291 298 } ··· 377 370 { 378 371 .driver_data = &acp6x_card, 379 372 .matches = { 373 + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), 374 + DMI_MATCH(DMI_BOARD_NAME, "8B2F"), 375 + } 376 + }, 377 + { 378 + .driver_data = &acp6x_card, 379 + .matches = { 380 380 DMI_MATCH(DMI_BOARD_VENDOR, "MECHREVO"), 381 381 DMI_MATCH(DMI_BOARD_NAME, "MRID6"), 382 382 } ··· 393 379 .matches = { 394 380 DMI_MATCH(DMI_BOARD_VENDOR, "System76"), 395 381 DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"), 382 + } 383 + }, 384 + { 385 + .driver_data = &acp6x_card, 386 + .matches = { 387 + DMI_MATCH(DMI_BOARD_VENDOR, "System76"), 388 + DMI_MATCH(DMI_PRODUCT_VERSION, "pang13"), 396 389 } 397 390 }, 398 391 {}
+3 -3
sound/soc/codecs/cs43130.c
··· 578 578 break; 579 579 case SND_SOC_DAIFMT_LEFT_J: 580 580 hi_size = bitwidth_sclk; 581 - frm_delay = 2; 581 + frm_delay = 0; 582 582 frm_phase = 1; 583 583 break; 584 584 case SND_SOC_DAIFMT_DSP_A: ··· 1682 1682 return cs43130_show_dc(dev, buf, HP_RIGHT); 1683 1683 } 1684 1684 1685 - static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = { 1685 + static const u16 cs43130_ac_freq[CS43130_AC_FREQ] = { 1686 1686 24, 1687 1687 43, 1688 1688 93, ··· 2362 2362 .use_single_write = true, 2363 2363 }; 2364 2364 2365 - static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = { 2365 + static const u16 cs43130_dc_threshold[CS43130_DC_THRESHOLD] = { 2366 2366 50, 2367 2367 120, 2368 2368 };
+1 -1
sound/soc/codecs/da7219-aad.c
··· 696 696 aad_pdata->mic_det_thr = 697 697 da7219_aad_fw_mic_det_thr(dev, fw_val32); 698 698 else 699 - aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS; 699 + aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_200_OHMS; 700 700 701 701 if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0) 702 702 aad_pdata->jack_ins_deb =
+20 -3
sound/soc/codecs/hdac_hda.c
··· 132 132 .sig_bits = 24, 133 133 }, 134 134 }, 135 + }; 136 + 137 + static struct snd_soc_dai_driver hdac_hda_hdmi_dais[] = { 135 138 { 136 139 .id = HDAC_HDMI_0_DAI_ID, 137 140 .name = "intel-hdmi-hifi1", ··· 610 607 .endianness = 1, 611 608 }; 612 609 610 + static const struct snd_soc_component_driver hdac_hda_hdmi_codec = { 611 + .probe = hdac_hda_codec_probe, 612 + .remove = hdac_hda_codec_remove, 613 + .idle_bias_on = false, 614 + .endianness = 1, 615 + }; 616 + 613 617 static int hdac_hda_dev_probe(struct hdac_device *hdev) 614 618 { 619 + struct hdac_hda_priv *hda_pvt = dev_get_drvdata(&hdev->dev); 615 620 struct hdac_ext_link *hlink; 616 621 int ret; 617 622 ··· 632 621 snd_hdac_ext_bus_link_get(hdev->bus, hlink); 633 622 634 623 /* ASoC specific initialization */ 635 - ret = devm_snd_soc_register_component(&hdev->dev, 636 - &hdac_hda_codec, hdac_hda_dais, 637 - ARRAY_SIZE(hdac_hda_dais)); 624 + if (hda_pvt->need_display_power) 625 + ret = devm_snd_soc_register_component(&hdev->dev, 626 + &hdac_hda_hdmi_codec, hdac_hda_hdmi_dais, 627 + ARRAY_SIZE(hdac_hda_hdmi_dais)); 628 + else 629 + ret = devm_snd_soc_register_component(&hdev->dev, 630 + &hdac_hda_codec, hdac_hda_dais, 631 + ARRAY_SIZE(hdac_hda_dais)); 632 + 638 633 if (ret < 0) { 639 634 dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret); 640 635 return ret;
+5
sound/soc/codecs/lpass-tx-macro.c
··· 2021 2021 2022 2022 tx->dev = dev; 2023 2023 2024 + /* Set active_decimator default value */ 2025 + tx->active_decimator[TX_MACRO_AIF1_CAP] = -1; 2026 + tx->active_decimator[TX_MACRO_AIF2_CAP] = -1; 2027 + tx->active_decimator[TX_MACRO_AIF3_CAP] = -1; 2028 + 2024 2029 /* set MCLK and NPL rates */ 2025 2030 clk_set_rate(tx->mclk, MCLK_FREQ); 2026 2031 clk_set_rate(tx->npl, MCLK_FREQ);
+6 -3
sound/soc/codecs/nau8822.c
··· 184 184 struct soc_bytes_ext *params = (void *)kcontrol->private_value; 185 185 int i, reg; 186 186 u16 reg_val, *val; 187 + __be16 tmp; 187 188 188 189 val = (u16 *)ucontrol->value.bytes.data; 189 190 reg = NAU8822_REG_EQ1; ··· 193 192 /* conversion of 16-bit integers between native CPU format 194 193 * and big endian format 195 194 */ 196 - reg_val = cpu_to_be16(reg_val); 197 - memcpy(val + i, &reg_val, sizeof(reg_val)); 195 + tmp = cpu_to_be16(reg_val); 196 + memcpy(val + i, &tmp, sizeof(tmp)); 198 197 } 199 198 200 199 return 0; ··· 217 216 void *data; 218 217 u16 *val, value; 219 218 int i, reg, ret; 219 + __be16 *tmp; 220 220 221 221 data = kmemdup(ucontrol->value.bytes.data, 222 222 params->max, GFP_KERNEL | GFP_DMA); ··· 230 228 /* conversion of 16-bit integers between native CPU format 231 229 * and big endian format 232 230 */ 233 - value = be16_to_cpu(*(val + i)); 231 + tmp = (__be16 *)(val + i); 232 + value = be16_to_cpup(tmp); 234 233 ret = snd_soc_component_write(component, reg + i, value); 235 234 if (ret) { 236 235 dev_err(component->dev,
+9 -1
sound/soc/codecs/rt5645.c
··· 448 448 struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)]; 449 449 struct rt5645_eq_param_s *eq_param; 450 450 struct timer_list btn_check_timer; 451 + struct mutex jd_mutex; 451 452 452 453 int codec_type; 453 454 int sysclk; ··· 3194 3193 rt5645_enable_push_button_irq(component, true); 3195 3194 } 3196 3195 } else { 3196 + if (rt5645->en_button_func) 3197 + rt5645_enable_push_button_irq(component, false); 3197 3198 snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); 3198 3199 snd_soc_dapm_sync(dapm); 3199 3200 rt5645->jack_type = SND_JACK_HEADPHONE; ··· 3298 3295 if (!rt5645->component) 3299 3296 return; 3300 3297 3298 + mutex_lock(&rt5645->jd_mutex); 3299 + 3301 3300 switch (rt5645->pdata.jd_mode) { 3302 3301 case 0: /* Not using rt5645 JD */ 3303 3302 if (rt5645->gpiod_hp_det) { ··· 3326 3321 3327 3322 if (!val && (rt5645->jack_type == 0)) { /* jack in */ 3328 3323 report = rt5645_jack_detect(rt5645->component, 1); 3329 - } else if (!val && rt5645->jack_type != 0) { 3324 + } else if (!val && rt5645->jack_type == SND_JACK_HEADSET) { 3330 3325 /* for push button and jack out */ 3331 3326 btn_type = 0; 3332 3327 if (snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) { ··· 3381 3376 RT5645_INT_IRQ_ST, 0x1, 0x0); 3382 3377 rt5645_jack_detect(rt5645->component, 0); 3383 3378 } 3379 + 3380 + mutex_unlock(&rt5645->jd_mutex); 3384 3381 3385 3382 snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); 3386 3383 snd_soc_jack_report(rt5645->mic_jack, report, SND_JACK_MICROPHONE); ··· 4157 4150 } 4158 4151 timer_setup(&rt5645->btn_check_timer, rt5645_btn_check_callback, 0); 4159 4152 4153 + mutex_init(&rt5645->jd_mutex); 4160 4154 INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); 4161 4155 INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work); 4162 4156
+3 -3
sound/soc/codecs/wm8974.c
··· 186 186 187 187 /* Boost mixer */ 188 188 static const struct snd_kcontrol_new wm8974_boost_mixer[] = { 189 - SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 1), 189 + SOC_DAPM_SINGLE("PGA Switch", WM8974_INPPGA, 6, 1, 1), 190 190 }; 191 191 192 192 /* Input PGA */ ··· 246 246 247 247 /* Boost Mixer */ 248 248 {"ADC", NULL, "Boost Mixer"}, 249 - {"Boost Mixer", "Aux Switch", "Aux Input"}, 250 - {"Boost Mixer", NULL, "Input PGA"}, 249 + {"Boost Mixer", NULL, "Aux Input"}, 250 + {"Boost Mixer", "PGA Switch", "Input PGA"}, 251 251 {"Boost Mixer", NULL, "MICP"}, 252 252 253 253 /* Input PGA */
+6 -2
sound/soc/codecs/wm_adsp.c
··· 1451 1451 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset, 1452 1452 &region->base_addr); 1453 1453 if (ret < 0) 1454 - return ret; 1454 + goto err; 1455 1455 1456 1456 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset, 1457 1457 &offset); 1458 1458 if (ret < 0) 1459 - return ret; 1459 + goto err; 1460 1460 1461 1461 region->cumulative_size = offset; 1462 1462 ··· 1467 1467 } 1468 1468 1469 1469 return 0; 1470 + 1471 + err: 1472 + kfree(buf->regions); 1473 + return ret; 1470 1474 } 1471 1475 1472 1476 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
+1
sound/soc/fsl/Kconfig
··· 360 360 config SND_SOC_IMX_RPMSG 361 361 tristate "SoC Audio support for i.MX boards with rpmsg" 362 362 depends on RPMSG 363 + depends on OF && I2C 363 364 select SND_SOC_IMX_PCM_RPMSG 364 365 select SND_SOC_IMX_AUDIO_RPMSG 365 366 help
+21
sound/soc/fsl/fsl_sai.c
··· 673 673 FSL_SAI_CR3_TRCE_MASK, 674 674 FSL_SAI_CR3_TRCE((dl_cfg[dl_cfg_idx].mask[tx] & trce_mask))); 675 675 676 + /* 677 + * When the TERE and FSD_MSTR enabled before configuring the word width 678 + * There will be no frame sync clock issue, because word width impact 679 + * the generation of frame sync clock. 680 + * 681 + * TERE enabled earlier only for i.MX8MP case for the hardware limitation, 682 + * We need to disable FSD_MSTR before configuring word width, then enable 683 + * FSD_MSTR bit for this specific case. 684 + */ 685 + if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && 686 + !sai->is_consumer_mode) 687 + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), 688 + FSL_SAI_CR4_FSD_MSTR, 0); 689 + 676 690 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), 677 691 FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK | 678 692 FSL_SAI_CR4_CHMOD_MASK, ··· 694 680 regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs), 695 681 FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | 696 682 FSL_SAI_CR5_FBT_MASK, val_cr5); 683 + 684 + /* Enable FSD_MSTR after configuring word width */ 685 + if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && 686 + !sai->is_consumer_mode) 687 + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), 688 + FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR); 689 + 697 690 regmap_write(sai->regmap, FSL_SAI_xMR(tx), 698 691 ~0UL - ((1 << min(channels, slots)) - 1)); 699 692
+12 -2
sound/soc/fsl/fsl_xcvr.c
··· 358 358 struct device *dev = &xcvr->pdev->dev; 359 359 int ret; 360 360 361 - freq = xcvr->soc_data->spdif_only ? freq / 10 : freq; 361 + freq = xcvr->soc_data->spdif_only ? freq / 5 : freq; 362 362 clk_disable_unprepare(xcvr->phy_clk); 363 363 ret = clk_set_rate(xcvr->phy_clk, freq); 364 364 if (ret < 0) { ··· 409 409 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 410 410 u32 m_ctl = 0, v_ctl = 0; 411 411 u32 r = substream->runtime->rate, ch = substream->runtime->channels; 412 - u32 fout = 32 * r * ch * 10 * 2; 412 + u32 fout = 32 * r * ch * 10; 413 413 int ret = 0; 414 414 415 415 switch (xcvr->mode) { 416 416 case FSL_XCVR_MODE_SPDIF: 417 + if (xcvr->soc_data->spdif_only && tx) { 418 + ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET, 419 + FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM, 420 + FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM); 421 + if (ret < 0) { 422 + dev_err(dai->dev, "Failed to set bypass fem: %d\n", ret); 423 + return ret; 424 + } 425 + } 426 + fallthrough; 417 427 case FSL_XCVR_MODE_ARC: 418 428 if (tx) { 419 429 ret = fsl_xcvr_en_aud_pll(xcvr, fout);
+2
sound/soc/intel/boards/skl_hda_dsp_generic.c
··· 154 154 card->dapm_widgets = skl_hda_widgets; 155 155 card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); 156 156 if (!ctx->idisp_codec) { 157 + card->dapm_routes = &skl_hda_map[IDISP_ROUTE_COUNT]; 158 + num_route -= IDISP_ROUTE_COUNT; 157 159 for (i = 0; i < IDISP_DAI_COUNT; i++) { 158 160 skl_hda_be_dai_links[i].codecs = &snd_soc_dummy_dlc; 159 161 skl_hda_be_dai_links[i].num_codecs = 1;
+9 -8
sound/soc/intel/boards/sof_sdw.c
··· 1546 1546 { 1547 1547 struct device *dev = card->dev; 1548 1548 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); 1549 - int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, hdmi_num = 0, bt_num = 0; 1549 + int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; 1550 1550 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 1551 1551 struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; 1552 1552 const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; ··· 1564 1564 char *codec_name, *codec_dai_name; 1565 1565 int i, j, be_id = 0; 1566 1566 int codec_index; 1567 + int hdmi_num; 1567 1568 int ret; 1568 1569 1569 1570 ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); ··· 1585 1584 ssp_num = hweight_long(ssp_mask); 1586 1585 } 1587 1586 1588 - if (mach_params->codec_mask & IDISP_CODEC_MASK) { 1587 + if (mach_params->codec_mask & IDISP_CODEC_MASK) 1589 1588 ctx->hdmi.idisp_codec = true; 1590 1589 1591 - if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1592 - hdmi_num = SOF_TGL_HDMI_COUNT; 1593 - else 1594 - hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1595 - } 1590 + if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) 1591 + hdmi_num = SOF_TGL_HDMI_COUNT; 1592 + else 1593 + hdmi_num = SOF_PRE_TGL_HDMI_COUNT; 1596 1594 1597 1595 /* enable dmic01 & dmic16k */ 1598 1596 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ··· 1601 1601 bt_num = 1; 1602 1602 1603 1603 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", 1604 - sdw_be_num, ssp_num, dmic_num, hdmi_num, bt_num); 1604 + sdw_be_num, ssp_num, dmic_num, 1605 + ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); 1605 1606 1606 1607 /* allocate BE dailinks */ 1607 1608 num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
+7 -2
sound/soc/intel/skylake/skl-pcm.c
··· 240 240 snd_pcm_set_sync(substream); 241 241 242 242 mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 243 - if (!mconfig) 243 + if (!mconfig) { 244 + kfree(dma_params); 244 245 return -EINVAL; 246 + } 245 247 246 248 skl_tplg_d0i3_get(skl, mconfig->d0i3_caps); 247 249 ··· 1464 1462 dais = krealloc(skl->dais, sizeof(skl_fe_dai) + 1465 1463 sizeof(skl_platform_dai), GFP_KERNEL); 1466 1464 if (!dais) { 1465 + kfree(skl->dais); 1467 1466 ret = -ENOMEM; 1468 1467 goto err; 1469 1468 } ··· 1477 1474 1478 1475 ret = devm_snd_soc_register_component(dev, &skl_component, 1479 1476 skl->dais, num_dais); 1480 - if (ret) 1477 + if (ret) { 1478 + kfree(skl->dais); 1481 1479 dev_err(dev, "soc component registration failed %d\n", ret); 1480 + } 1482 1481 err: 1483 1482 return ret; 1484 1483 }
+3 -1
sound/soc/intel/skylake/skl-sst-ipc.c
··· 1003 1003 1004 1004 reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK; 1005 1005 buf = krealloc(reply.data, reply.size, GFP_KERNEL); 1006 - if (!buf) 1006 + if (!buf) { 1007 + kfree(reply.data); 1007 1008 return -ENOMEM; 1009 + } 1008 1010 *payload = buf; 1009 1011 *bytes = reply.size; 1010 1012
+17
sound/soc/qcom/sc8280xp.c
··· 27 27 static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) 28 28 { 29 29 struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 30 + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 31 + struct snd_soc_card *card = rtd->card; 32 + 33 + switch (cpu_dai->id) { 34 + case WSA_CODEC_DMA_RX_0: 35 + case WSA_CODEC_DMA_RX_1: 36 + /* 37 + * set limit of 0dB on Digital Volume for Speakers, 38 + * this can prevent damage of speakers to some extent without 39 + * active speaker protection 40 + */ 41 + snd_soc_limit_volume(card, "WSA_RX0 Digital Volume", 84); 42 + snd_soc_limit_volume(card, "WSA_RX1 Digital Volume", 84); 43 + break; 44 + default: 45 + break; 46 + } 30 47 31 48 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 32 49 }
+1 -1
sound/soc/soc-ops.c
··· 661 661 kctl = snd_soc_card_get_kcontrol(card, name); 662 662 if (kctl) { 663 663 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 664 - if (max <= mc->max) { 664 + if (max <= mc->max - mc->min) { 665 665 mc->platform_max = max; 666 666 ret = 0; 667 667 }
+4 -7
sound/soc/soc-pcm.c
··· 704 704 if (snd_soc_dai_active(dai) == 0 && 705 705 (dai->rate || dai->channels || dai->sample_bits)) 706 706 soc_pcm_set_dai_params(dai, NULL); 707 - 708 - if (snd_soc_dai_stream_active(dai, substream->stream) == 0) { 709 - if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger) 710 - snd_soc_dai_digital_mute(dai, 1, substream->stream); 711 - } 712 707 } 713 708 } 714 709 ··· 942 947 if (snd_soc_dai_active(dai) == 1) 943 948 soc_pcm_set_dai_params(dai, NULL); 944 949 945 - if (snd_soc_dai_stream_active(dai, substream->stream) == 1) 946 - snd_soc_dai_digital_mute(dai, 1, substream->stream); 950 + if (snd_soc_dai_stream_active(dai, substream->stream) == 1) { 951 + if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger) 952 + snd_soc_dai_digital_mute(dai, 1, substream->stream); 953 + } 947 954 } 948 955 949 956 /* run the stream event */
+2
sound/soc/sof/ipc3-topology.c
··· 493 493 static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) 494 494 { 495 495 struct snd_soc_component *scomp = swidget->scomp; 496 + struct snd_sof_pipeline *spipe = swidget->spipe; 496 497 struct sof_ipc_pipe_new *pipeline; 497 498 struct snd_sof_widget *comp_swidget; 498 499 int ret; ··· 546 545 swidget->dynamic_pipeline_widget); 547 546 548 547 swidget->core = pipeline->core; 548 + spipe->core_mask |= BIT(pipeline->core); 549 549 550 550 return 0; 551 551
+10 -10
sound/soc/sof/ipc4-control.c
··· 89 89 struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 90 90 struct sof_ipc4_gain *gain = swidget->private; 91 91 struct sof_ipc4_msg *msg = &cdata->msg; 92 - struct sof_ipc4_gain_data data; 92 + struct sof_ipc4_gain_params params; 93 93 bool all_channels_equal = true; 94 94 u32 value; 95 95 int ret, i; ··· 109 109 */ 110 110 for (i = 0; i < scontrol->num_channels; i++) { 111 111 if (all_channels_equal) { 112 - data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; 113 - data.init_val = cdata->chanv[0].value; 112 + params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; 113 + params.init_val = cdata->chanv[0].value; 114 114 } else { 115 - data.channels = cdata->chanv[i].channel; 116 - data.init_val = cdata->chanv[i].value; 115 + params.channels = cdata->chanv[i].channel; 116 + params.init_val = cdata->chanv[i].value; 117 117 } 118 118 119 119 /* set curve type and duration from topology */ 120 - data.curve_duration_l = gain->data.curve_duration_l; 121 - data.curve_duration_h = gain->data.curve_duration_h; 122 - data.curve_type = gain->data.curve_type; 120 + params.curve_duration_l = gain->data.params.curve_duration_l; 121 + params.curve_duration_h = gain->data.params.curve_duration_h; 122 + params.curve_type = gain->data.params.curve_type; 123 123 124 - msg->data_ptr = &data; 125 - msg->data_size = sizeof(data); 124 + msg->data_ptr = &params; 125 + msg->data_size = sizeof(params); 126 126 127 127 ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock); 128 128 msg->data_ptr = NULL;
+35 -26
sound/soc/sof/ipc4-topology.c
··· 130 130 131 131 static const struct sof_topology_token gain_tokens[] = { 132 132 {SOF_TKN_GAIN_RAMP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, 133 - get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)}, 133 + get_token_u32, offsetof(struct sof_ipc4_gain_params, curve_type)}, 134 134 {SOF_TKN_GAIN_RAMP_DURATION, 135 135 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 136 - offsetof(struct sof_ipc4_gain_data, curve_duration_l)}, 136 + offsetof(struct sof_ipc4_gain_params, curve_duration_l)}, 137 137 {SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD, 138 - get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)}, 138 + get_token_u32, offsetof(struct sof_ipc4_gain_params, init_val)}, 139 139 }; 140 140 141 141 /* SRC */ 142 142 static const struct sof_topology_token src_tokens[] = { 143 143 {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 144 - offsetof(struct sof_ipc4_src, sink_rate)}, 144 + offsetof(struct sof_ipc4_src_data, sink_rate)}, 145 145 }; 146 146 147 147 static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { ··· 656 656 { 657 657 struct snd_soc_component *scomp = swidget->scomp; 658 658 struct sof_ipc4_pipeline *pipeline; 659 + struct snd_sof_pipeline *spipe = swidget->spipe; 659 660 int ret; 660 661 661 662 pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL); ··· 671 670 } 672 671 673 672 swidget->core = pipeline->core_id; 673 + spipe->core_mask |= BIT(pipeline->core_id); 674 674 675 675 if (pipeline->use_chain_dma) { 676 676 dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name); ··· 720 718 721 719 swidget->private = gain; 722 720 723 - gain->data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; 724 - gain->data.init_val = SOF_IPC4_VOL_ZERO_DB; 721 + gain->data.params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; 722 + gain->data.params.init_val = SOF_IPC4_VOL_ZERO_DB; 725 723 726 - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config); 724 + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->data.base_config); 727 725 if (ret) 728 726 goto err; 729 727 730 - ret = sof_update_ipc_object(scomp, &gain->data, SOF_GAIN_TOKENS, swidget->tuples, 731 - swidget->num_tuples, sizeof(gain->data), 1); 728 + ret = sof_update_ipc_object(scomp, &gain->data.params, SOF_GAIN_TOKENS, 729 + swidget->tuples, swidget->num_tuples, sizeof(gain->data), 1); 732 730 if (ret) { 733 731 dev_err(scomp->dev, "Parsing gain tokens failed\n"); 734 732 goto err; ··· 736 734 737 735 dev_dbg(scomp->dev, 738 736 "pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x\n", 739 - swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l, 740 - gain->data.init_val); 737 + swidget->widget->name, gain->data.params.curve_type, 738 + gain->data.params.curve_duration_l, gain->data.params.init_val); 741 739 742 740 ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg); 743 741 if (ret) ··· 799 797 static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) 800 798 { 801 799 struct snd_soc_component *scomp = swidget->scomp; 800 + struct snd_sof_pipeline *spipe = swidget->spipe; 802 801 struct sof_ipc4_src *src; 803 802 int ret; 804 803 ··· 811 808 812 809 swidget->private = src; 813 810 814 - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config); 811 + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, 812 + &src->data.base_config); 815 813 if (ret) 816 814 goto err; 817 815 818 - ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples, 816 + ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples, 819 817 swidget->num_tuples, sizeof(*src), 1); 820 818 if (ret) { 821 819 dev_err(scomp->dev, "Parsing SRC tokens failed\n"); 822 820 goto err; 823 821 } 824 822 825 - dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate); 823 + spipe->core_mask |= BIT(swidget->core); 824 + 825 + dev_dbg(scomp->dev, "SRC sink rate %d\n", src->data.sink_rate); 826 826 827 827 ret = sof_ipc4_widget_setup_msg(swidget, &src->msg); 828 828 if (ret) ··· 870 864 { 871 865 struct snd_soc_component *scomp = swidget->scomp; 872 866 struct sof_ipc4_fw_module *fw_module; 867 + struct snd_sof_pipeline *spipe = swidget->spipe; 873 868 struct sof_ipc4_process *process; 874 869 void *cfg; 875 870 int ret; ··· 926 919 process->ipc_config_data = cfg; 927 920 928 921 sof_ipc4_widget_update_kcontrol_module_id(swidget); 922 + 923 + /* set pipeline core mask to keep track of the core the module is scheduled to run on */ 924 + spipe->core_mask |= BIT(swidget->core); 929 925 930 926 return 0; 931 927 free_base_cfg_ext: ··· 1826 1816 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1827 1817 int ret; 1828 1818 1829 - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->base_config, 1819 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->data.base_config, 1830 1820 pipeline_params, available_fmt); 1831 1821 if (ret < 0) 1832 1822 return ret; ··· 1836 1826 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1837 1827 out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1838 1828 1839 - ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->base_config, available_fmt, 1829 + ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->data.base_config, available_fmt, 1840 1830 out_ref_rate, out_ref_channels, out_ref_valid_bits); 1841 1831 if (ret < 0) { 1842 1832 dev_err(sdev->dev, "Failed to initialize output format for %s", ··· 1845 1835 } 1846 1836 1847 1837 /* update pipeline memory usage */ 1848 - sof_ipc4_update_resource_usage(sdev, swidget, &gain->base_config); 1838 + sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config); 1849 1839 1850 1840 return 0; 1851 1841 } ··· 1901 1891 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1902 1892 int output_format_index, input_format_index; 1903 1893 1904 - input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->base_config, 1894 + input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->data.base_config, 1905 1895 pipeline_params, available_fmt); 1906 1896 if (input_format_index < 0) 1907 1897 return input_format_index; ··· 1931 1921 */ 1932 1922 out_ref_rate = params_rate(fe_params); 1933 1923 1934 - output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, 1924 + output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->data.base_config, 1935 1925 available_fmt, out_ref_rate, 1936 1926 out_ref_channels, out_ref_valid_bits); 1937 1927 if (output_format_index < 0) { ··· 1941 1931 } 1942 1932 1943 1933 /* update pipeline memory usage */ 1944 - sof_ipc4_update_resource_usage(sdev, swidget, &src->base_config); 1934 + sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config); 1945 1935 1946 1936 out_audio_fmt = &available_fmt->output_pin_fmts[output_format_index].audio_fmt; 1947 - src->sink_rate = out_audio_fmt->sampling_frequency; 1937 + src->data.sink_rate = out_audio_fmt->sampling_frequency; 1948 1938 1949 1939 /* update pipeline_params for sink widgets */ 1950 1940 return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt); ··· 2324 2314 { 2325 2315 struct sof_ipc4_gain *gain = swidget->private; 2326 2316 2327 - ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + 2328 - sizeof(struct sof_ipc4_gain_data); 2329 - ipc_data = gain; 2317 + ipc_size = sizeof(gain->data); 2318 + ipc_data = &gain->data; 2330 2319 2331 2320 msg = &gain->msg; 2332 2321 break; ··· 2344 2335 { 2345 2336 struct sof_ipc4_src *src = swidget->private; 2346 2337 2347 - ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate); 2348 - ipc_data = src; 2338 + ipc_size = sizeof(src->data); 2339 + ipc_data = &src->data; 2349 2340 2350 2341 msg = &src->msg; 2351 2342 break;
+25 -9
sound/soc/sof/ipc4-topology.h
··· 361 361 } __packed; 362 362 363 363 /** 364 - * struct sof_ipc4_gain_data - IPC gain blob 364 + * struct sof_ipc4_gain_params - IPC gain parameters 365 365 * @channels: Channels 366 366 * @init_val: Initial value 367 367 * @curve_type: Curve type ··· 369 369 * @curve_duration_l: Curve duration low part 370 370 * @curve_duration_h: Curve duration high part 371 371 */ 372 - struct sof_ipc4_gain_data { 372 + struct sof_ipc4_gain_params { 373 373 uint32_t channels; 374 374 uint32_t init_val; 375 375 uint32_t curve_type; 376 376 uint32_t reserved; 377 377 uint32_t curve_duration_l; 378 378 uint32_t curve_duration_h; 379 - } __aligned(8); 379 + } __packed __aligned(4); 380 + 381 + /** 382 + * struct sof_ipc4_gain_data - IPC gain init blob 383 + * @base_config: IPC base config data 384 + * @params: Initial parameters for the gain module 385 + */ 386 + struct sof_ipc4_gain_data { 387 + struct sof_ipc4_base_module_cfg base_config; 388 + struct sof_ipc4_gain_params params; 389 + } __packed __aligned(4); 380 390 381 391 /** 382 392 * struct sof_ipc4_gain - gain config data 383 - * @base_config: IPC base config data 384 393 * @data: IPC gain blob 385 394 * @available_fmt: Available audio format 386 395 * @msg: message structure for gain 387 396 */ 388 397 struct sof_ipc4_gain { 389 - struct sof_ipc4_base_module_cfg base_config; 390 398 struct sof_ipc4_gain_data data; 391 399 struct sof_ipc4_available_audio_format available_fmt; 392 400 struct sof_ipc4_msg msg; ··· 412 404 struct sof_ipc4_msg msg; 413 405 }; 414 406 415 - /** 416 - * struct sof_ipc4_src SRC config data 407 + /* 408 + * struct sof_ipc4_src_data - IPC data for SRC 417 409 * @base_config: IPC base config data 418 410 * @sink_rate: Output rate for sink module 411 + */ 412 + struct sof_ipc4_src_data { 413 + struct sof_ipc4_base_module_cfg base_config; 414 + uint32_t sink_rate; 415 + } __packed __aligned(4); 416 + 417 + /** 418 + * struct sof_ipc4_src - SRC config data 419 + * @data: IPC base config data 419 420 * @available_fmt: Available audio format 420 421 * @msg: IPC4 message struct containing header and data info 421 422 */ 422 423 struct sof_ipc4_src { 423 - struct sof_ipc4_base_module_cfg base_config; 424 - uint32_t sink_rate; 424 + struct sof_ipc4_src_data data; 425 425 struct sof_ipc4_available_audio_format available_fmt; 426 426 struct sof_ipc4_msg msg; 427 427 };
+3
sound/soc/sof/mediatek/mt8186/mt8186.c
··· 597 597 598 598 static struct snd_sof_of_mach sof_mt8186_machs[] = { 599 599 { 600 + .compatible = "google,steelix", 601 + .sof_tplg_filename = "sof-mt8186-google-steelix.tplg" 602 + }, { 600 603 .compatible = "mediatek,mt8186", 601 604 .sof_tplg_filename = "sof-mt8186.tplg", 602 605 },
+41 -24
sound/soc/sof/sof-audio.c
··· 46 46 struct snd_sof_widget *swidget) 47 47 { 48 48 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 49 + struct snd_sof_pipeline *spipe = swidget->spipe; 49 50 struct snd_sof_widget *pipe_widget; 50 51 int err = 0; 51 52 int ret; ··· 88 87 } 89 88 90 89 /* 91 - * disable widget core. continue to route setup status and complete flag 92 - * even if this fails and return the appropriate error 90 + * decrement ref count for cores associated with all modules in the pipeline and clear 91 + * the complete flag 93 92 */ 94 - ret = snd_sof_dsp_core_put(sdev, swidget->core); 95 - if (ret < 0) { 96 - dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n", 97 - swidget->core, swidget->widget->name); 98 - if (!err) 99 - err = ret; 93 + if (swidget->id == snd_soc_dapm_scheduler) { 94 + int i; 95 + 96 + for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { 97 + ret = snd_sof_dsp_core_put(sdev, i); 98 + if (ret < 0) { 99 + dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n", 100 + i, swidget->widget->name); 101 + if (!err) 102 + err = ret; 103 + } 104 + } 105 + swidget->spipe->complete = 0; 100 106 } 101 107 102 108 /* ··· 115 107 if (ret < 0 && !err) 116 108 err = ret; 117 109 } 118 - 119 - /* clear pipeline complete */ 120 - if (swidget->id == snd_soc_dapm_scheduler) 121 - swidget->spipe->complete = 0; 122 110 123 111 if (!err) 124 112 dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name); ··· 138 134 struct snd_sof_widget *swidget) 139 135 { 140 136 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 137 + struct snd_sof_pipeline *spipe = swidget->spipe; 141 138 bool use_count_decremented = false; 142 139 int ret; 140 + int i; 143 141 144 142 /* skip if there is no private data */ 145 143 if (!swidget->private) ··· 172 166 goto use_count_dec; 173 167 } 174 168 175 - /* enable widget core */ 176 - ret = snd_sof_dsp_core_get(sdev, swidget->core); 177 - if (ret < 0) { 178 - dev_err(sdev->dev, "error: failed to enable target core for widget %s\n", 179 - swidget->widget->name); 180 - goto pipe_widget_free; 169 + /* update ref count for cores associated with all modules in the pipeline */ 170 + if (swidget->id == snd_soc_dapm_scheduler) { 171 + for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { 172 + ret = snd_sof_dsp_core_get(sdev, i); 173 + if (ret < 0) { 174 + dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n", 175 + i, swidget->widget->name); 176 + goto pipe_widget_free; 177 + } 178 + } 181 179 } 182 180 183 181 /* setup widget in the DSP */ 184 182 if (tplg_ops && tplg_ops->widget_setup) { 185 183 ret = tplg_ops->widget_setup(sdev, swidget); 186 184 if (ret < 0) 187 - goto core_put; 185 + goto pipe_widget_free; 188 186 } 189 187 190 188 /* send config for DAI components */ ··· 218 208 return 0; 219 209 220 210 widget_free: 221 - /* widget use_count and core ref_count will both be decremented by sof_widget_free() */ 211 + /* widget use_count will be decremented by sof_widget_free() */ 222 212 sof_widget_free_unlocked(sdev, swidget); 223 213 use_count_decremented = true; 224 - core_put: 225 - if (!use_count_decremented) 226 - snd_sof_dsp_core_put(sdev, swidget->core); 227 214 pipe_widget_free: 228 - if (swidget->id != snd_soc_dapm_scheduler) 215 + if (swidget->id != snd_soc_dapm_scheduler) { 229 216 sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); 217 + } else { 218 + int j; 219 + 220 + /* decrement ref count for all cores that were updated previously */ 221 + for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) { 222 + if (j >= i) 223 + break; 224 + snd_sof_dsp_core_put(sdev, j); 225 + } 226 + } 230 227 use_count_dec: 231 228 if (!use_count_decremented) 232 229 swidget->use_count--;
+2
sound/soc/sof/sof-audio.h
··· 480 480 * @paused_count: Count of number of PCM's that have started and have currently paused this 481 481 pipeline 482 482 * @complete: flag used to indicate that pipeline set up is complete. 483 + * @core_mask: Mask containing target cores for all modules in the pipeline 483 484 * @list: List item in sdev pipeline_list 484 485 */ 485 486 struct snd_sof_pipeline { ··· 488 487 int started_count; 489 488 int paused_count; 490 489 int complete; 490 + unsigned long core_mask; 491 491 struct list_head list; 492 492 }; 493 493
+3 -1
sound/soc/sof/topology.c
··· 1736 1736 /* perform pcm set op */ 1737 1737 if (ipc_pcm_ops && ipc_pcm_ops->pcm_setup) { 1738 1738 ret = ipc_pcm_ops->pcm_setup(sdev, spcm); 1739 - if (ret < 0) 1739 + if (ret < 0) { 1740 + kfree(spcm); 1740 1741 return ret; 1742 + } 1741 1743 } 1742 1744 1743 1745 dai_drv->dobj.private = spcm;