Merge the fixes branch up so we can apply further AMD work.
Unified · Split
| @@ -416,6 +416,7 @@ TripleX Chung <xxx.phy@gmail.com> <triplex@zh-kernel.org> · 415 unmodified lines | ||
| 416 | 416 | TripleX Chung <xxx.phy@gmail.com> <zhongyu@18mail.cn> |
| 417 | 417 | Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com> |
| 418 | 418 | Tycho Andersen <tycho@tycho.pizza> <tycho@tycho.ws> |
| 419 | +Tzung-Bi Shih <tzungbi@kernel.org> <tzungbi@google.com> | |
| 419 | 420 | Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de> |
| 420 | 421 | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| 421 | 422 | Uwe Kleine-König <ukleinek@strlen.de> |
| @@ -8,7 +8,7 @@ title: Audio codec controlled by ChromeOS EC · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | 10 | - Cheng-Yi Chiang <cychiang@chromium.org> |
| 11 | − - Tzung-Bi Shih <tzungbi@google.com> | |
| 11 | + - Tzung-Bi Shih <tzungbi@kernel.org> | |
| 12 | 12 | |
| 13 | 13 | description: | |
| 14 | 14 | Google's ChromeOS EC codec is a digital mic codec provided by the |
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Realtek rt1015p codec devicetree bindings |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Tzung-Bi Shih <tzungbi@google.com> | |
| 10 | + - Tzung-Bi Shih <tzungbi@kernel.org> | |
| 11 | 11 | |
| 12 | 12 | description: | |
| 13 | 13 | Rt1015p is a rt1015 variant which does not support I2C and |
| @@ -4911,7 +4911,7 @@ F: drivers/platform/chrome/ · 4910 unmodified lines | ||
| 4911 | 4911 | |
| 4912 | 4912 | CHROMEOS EC CODEC DRIVER |
| 4913 | 4913 | M: Cheng-Yi Chiang <cychiang@chromium.org> |
| 4914 | −M: Tzung-Bi Shih <tzungbi@google.com> | |
| 4914 | +M: Tzung-Bi Shih <tzungbi@kernel.org> | |
| 4915 | 4915 | R: Guenter Roeck <groeck@chromium.org> |
| 4916 | 4916 | L: chrome-platform@lists.linux.dev |
| 4917 | 4917 | S: Maintained |
| @@ -84,8 +84,8 @@ enum sof_ipc_dai_type { · 83 unmodified lines | ||
| 84 | 84 | SOF_DAI_AMD_BT, /**< AMD ACP BT*/ |
| 85 | 85 | SOF_DAI_AMD_SP, /**< AMD ACP SP */ |
| 86 | 86 | SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */ |
| 87 | − SOF_DAI_AMD_HS, /**< Amd HS */ | |
| 88 | 87 | SOF_DAI_MEDIATEK_AFE, /**< Mediatek AFE */ |
| 88 | + SOF_DAI_AMD_HS, /**< Amd HS */ | |
| 89 | 89 | }; |
| 90 | 90 | |
| 91 | 91 | /* general purpose DAI configuration */ |
| @@ -36,6 +36,10 @@ enum sof_ipc_ext_data { · 35 unmodified lines | ||
| 36 | 36 | SOF_IPC_EXT_USER_ABI_INFO = 4, |
| 37 | 37 | }; |
| 38 | 38 | |
| 39 | +/* Build u32 number in format MMmmmppp */ | |
| 40 | +#define SOF_FW_VER(MAJOR, MINOR, PATCH) ((uint32_t)( \ | |
| 41 | + ((MAJOR) << 24) | ((MINOR) << 12) | (PATCH))) | |
| 42 | + | |
| 39 | 43 | /* FW version - SOF_IPC_GLB_VERSION */ |
| 40 | 44 | struct sof_ipc_fw_version { |
| 41 | 45 | struct sof_ipc_hdr hdr; |
| @@ -320,6 +320,11 @@ static const struct config_entry config_table[] = { · 319 unmodified lines | ||
| 320 | 320 | {} |
| 321 | 321 | } |
| 322 | 322 | }, |
| 323 | + { | |
| 324 | + .flags = FLAG_SOF, | |
| 325 | + .device = 0x34c8, | |
| 326 | + .codec_hid = &essx_83x6, | |
| 327 | + }, | |
| 323 | 328 | { |
| 324 | 329 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 325 | 330 | .device = 0x34c8, |
| @@ -206,6 +206,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 205 unmodified lines | ||
| 206 | 206 | DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"), |
| 207 | 207 | } |
| 208 | 208 | }, |
| 209 | + { | |
| 210 | + .driver_data = &acp6x_card, | |
| 211 | + .matches = { | |
| 212 | + DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), | |
| 213 | + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), | |
| 214 | + } | |
| 215 | + }, | |
| 209 | 216 | {} |
| 210 | 217 | }; |
| 211 | 218 | |
| @@ -143,7 +143,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { · 142 unmodified lines | ||
| 143 | 143 | 0, 0xA0, 96, adc_att_tlv), |
| 144 | 144 | SOC_DOUBLE_R_SX_TLV("PGA Volume", |
| 145 | 145 | CS42L51_ALC_PGA_CTL, CS42L51_ALC_PGB_CTL, |
| 146 | − 0, 0x19, 30, pga_tlv), | |
| 146 | + 0, 0x1A, 30, pga_tlv), | |
| 147 | 147 | SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), |
| 148 | 148 | SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0), |
| 149 | 149 | SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0), |
| @@ -14,7 +14,7 @@ enum { · 13 unmodified lines | ||
| 14 | 14 | HDAC_HDMI_1_DAI_ID, |
| 15 | 15 | HDAC_HDMI_2_DAI_ID, |
| 16 | 16 | HDAC_HDMI_3_DAI_ID, |
| 17 | − HDAC_LAST_DAI_ID = HDAC_HDMI_3_DAI_ID, | |
| 17 | + HDAC_DAI_ID_NUM | |
| 18 | 18 | }; |
| 19 | 19 | |
| 20 | 20 | struct hdac_hda_pcm { |
| @@ -24,7 +24,7 @@ struct hdac_hda_pcm { · 3 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | struct hdac_hda_priv { |
| 26 | 26 | struct hda_codec *codec; |
| 27 | − struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID]; | |
| 27 | + struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM]; | |
| 28 | 28 | bool need_display_power; |
| 29 | 29 | }; |
| 30 | 30 | |
| @@ -549,6 +549,10 @@ static int max98373_i2c_probe(struct i2c_client *i2c) · 548 unmodified lines | ||
| 549 | 549 | max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num, |
| 550 | 550 | sizeof(*max98373->cache), |
| 551 | 551 | GFP_KERNEL); |
| 552 | + if (!max98373->cache) { | |
| 553 | + ret = -ENOMEM; | |
| 554 | + return ret; | |
| 555 | + } | |
| 552 | 556 | |
| 553 | 557 | for (i = 0; i < max98373->cache_num; i++) |
| 554 | 558 | max98373->cache[i].reg = max98373_i2c_cache_reg[i]; |
| @@ -298,13 +298,14 @@ static int rt5514_spi_pcm_new(struct snd_soc_component *component, · 297 unmodified lines | ||
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | static const struct snd_soc_component_driver rt5514_spi_component = { |
| 301 | − .name = DRV_NAME, | |
| 302 | − .probe = rt5514_spi_pcm_probe, | |
| 303 | − .open = rt5514_spi_pcm_open, | |
| 304 | − .hw_params = rt5514_spi_hw_params, | |
| 305 | − .hw_free = rt5514_spi_hw_free, | |
| 306 | − .pointer = rt5514_spi_pcm_pointer, | |
| 307 | − .pcm_construct = rt5514_spi_pcm_new, | |
| 301 | + .name = DRV_NAME, | |
| 302 | + .probe = rt5514_spi_pcm_probe, | |
| 303 | + .open = rt5514_spi_pcm_open, | |
| 304 | + .hw_params = rt5514_spi_hw_params, | |
| 305 | + .hw_free = rt5514_spi_hw_free, | |
| 306 | + .pointer = rt5514_spi_pcm_pointer, | |
| 307 | + .pcm_construct = rt5514_spi_pcm_new, | |
| 308 | + .legacy_dai_naming = 1, | |
| 308 | 309 | }; |
| 309 | 310 | |
| 310 | 311 | /** |
| @@ -396,15 +396,16 @@ static int rt5677_spi_pcm_probe(struct snd_soc_component *component) · 395 unmodified lines | ||
| 396 | 396 | } |
| 397 | 397 | |
| 398 | 398 | static const struct snd_soc_component_driver rt5677_spi_dai_component = { |
| 399 | − .name = DRV_NAME, | |
| 400 | − .probe = rt5677_spi_pcm_probe, | |
| 401 | − .open = rt5677_spi_pcm_open, | |
| 402 | − .close = rt5677_spi_pcm_close, | |
| 403 | − .hw_params = rt5677_spi_hw_params, | |
| 404 | − .hw_free = rt5677_spi_hw_free, | |
| 405 | − .prepare = rt5677_spi_prepare, | |
| 406 | − .pointer = rt5677_spi_pcm_pointer, | |
| 407 | − .pcm_construct = rt5677_spi_pcm_new, | |
| 399 | + .name = DRV_NAME, | |
| 400 | + .probe = rt5677_spi_pcm_probe, | |
| 401 | + .open = rt5677_spi_pcm_open, | |
| 402 | + .close = rt5677_spi_pcm_close, | |
| 403 | + .hw_params = rt5677_spi_hw_params, | |
| 404 | + .hw_free = rt5677_spi_hw_free, | |
| 405 | + .prepare = rt5677_spi_prepare, | |
| 406 | + .pointer = rt5677_spi_pcm_pointer, | |
| 407 | + .pcm_construct = rt5677_spi_pcm_new, | |
| 408 | + .legacy_dai_naming = 1, | |
| 408 | 409 | }; |
| 409 | 410 | |
| 410 | 411 | /* Select a suitable transfer command for the next transfer to ensure |
| @@ -230,7 +230,7 @@ static int rt711_sdca_read_prop(struct sdw_slave *slave) · 229 unmodified lines | ||
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | /* set the timeout values */ |
| 233 | − prop->clk_stop_timeout = 20; | |
| 233 | + prop->clk_stop_timeout = 700; | |
| 234 | 234 | |
| 235 | 235 | /* wake-up event */ |
| 236 | 236 | prop->wake_capable = 1; |
| @@ -1794,6 +1794,7 @@ static void sgtl5000_i2c_remove(struct i2c_client *client) · 1793 unmodified lines | ||
| 1794 | 1794 | { |
| 1795 | 1795 | struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); |
| 1796 | 1796 | |
| 1797 | + regmap_write(sgtl5000->regmap, SGTL5000_CHIP_CLK_CTRL, SGTL5000_CHIP_CLK_CTRL_DEFAULT); | |
| 1797 | 1798 | regmap_write(sgtl5000->regmap, SGTL5000_CHIP_DIG_POWER, SGTL5000_DIG_POWER_DEFAULT); |
| 1798 | 1799 | regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, SGTL5000_ANA_POWER_DEFAULT); |
| 1799 | 1800 | |
| @@ -438,20 +438,13 @@ static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai, · 437 unmodified lines | ||
| 438 | 438 | if (tx_mask == 0 || rx_mask != 0) |
| 439 | 439 | return -EINVAL; |
| 440 | 440 | |
| 441 | − if (slots == 1) { | |
| 442 | − if (tx_mask != 1) | |
| 443 | − return -EINVAL; | |
| 444 | − left_slot = 0; | |
| 445 | − right_slot = 0; | |
| 441 | + left_slot = __ffs(tx_mask); | |
| 442 | + tx_mask &= ~(1 << left_slot); | |
| 443 | + if (tx_mask == 0) { | |
| 444 | + right_slot = left_slot; | |
| 446 | 445 | } else { |
| 447 | − left_slot = __ffs(tx_mask); | |
| 448 | − tx_mask &= ~(1 << left_slot); | |
| 449 | − if (tx_mask == 0) { | |
| 450 | − right_slot = left_slot; | |
| 451 | − } else { | |
| 452 | − right_slot = __ffs(tx_mask); | |
| 453 | − tx_mask &= ~(1 << right_slot); | |
| 454 | − } | |
| 446 | + right_slot = __ffs(tx_mask); | |
| 447 | + tx_mask &= ~(1 << right_slot); | |
| 455 | 448 | } |
| 456 | 449 | |
| 457 | 450 | if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) |
| @@ -395,21 +395,13 @@ static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai, · 394 unmodified lines | ||
| 395 | 395 | if (tx_mask == 0 || rx_mask != 0) |
| 396 | 396 | return -EINVAL; |
| 397 | 397 | |
| 398 | − if (slots == 1) { | |
| 399 | − if (tx_mask != 1) | |
| 400 | − return -EINVAL; | |
| 401 | − | |
| 402 | − left_slot = 0; | |
| 403 | − right_slot = 0; | |
| 398 | + left_slot = __ffs(tx_mask); | |
| 399 | + tx_mask &= ~(1 << left_slot); | |
| 400 | + if (tx_mask == 0) { | |
| 401 | + right_slot = left_slot; | |
| 404 | 402 | } else { |
| 405 | − left_slot = __ffs(tx_mask); | |
| 406 | − tx_mask &= ~(1 << left_slot); | |
| 407 | − if (tx_mask == 0) { | |
| 408 | − right_slot = left_slot; | |
| 409 | − } else { | |
| 410 | − right_slot = __ffs(tx_mask); | |
| 411 | − tx_mask &= ~(1 << right_slot); | |
| 412 | − } | |
| 403 | + right_slot = __ffs(tx_mask); | |
| 404 | + tx_mask &= ~(1 << right_slot); | |
| 413 | 405 | } |
| 414 | 406 | |
| 415 | 407 | if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) |
| @@ -380,20 +380,13 @@ static int tas2780_set_dai_tdm_slot(struct snd_soc_dai *dai, · 379 unmodified lines | ||
| 380 | 380 | if (tx_mask == 0 || rx_mask != 0) |
| 381 | 381 | return -EINVAL; |
| 382 | 382 | |
| 383 | − if (slots == 1) { | |
| 384 | − if (tx_mask != 1) | |
| 385 | − return -EINVAL; | |
| 386 | − left_slot = 0; | |
| 387 | − right_slot = 0; | |
| 383 | + left_slot = __ffs(tx_mask); | |
| 384 | + tx_mask &= ~(1 << left_slot); | |
| 385 | + if (tx_mask == 0) { | |
| 386 | + right_slot = left_slot; | |
| 388 | 387 | } else { |
| 389 | − left_slot = __ffs(tx_mask); | |
| 390 | − tx_mask &= ~(1 << left_slot); | |
| 391 | − if (tx_mask == 0) { | |
| 392 | − right_slot = left_slot; | |
| 393 | − } else { | |
| 394 | − right_slot = __ffs(tx_mask); | |
| 395 | − tx_mask &= ~(1 << right_slot); | |
| 396 | − } | |
| 388 | + right_slot = __ffs(tx_mask); | |
| 389 | + tx_mask &= ~(1 << right_slot); | |
| 397 | 390 | } |
| 398 | 391 | |
| 399 | 392 | if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <dt-bindings/sound/tlv320adc3xxx.h> |
| 16 | 16 | #include <linux/clk.h> |
| 17 | +#include <linux/gpio/consumer.h> | |
| 17 | 18 | #include <linux/module.h> |
| 18 | 19 | #include <linux/moduleparam.h> |
| 19 | 20 | #include <linux/io.h> |
| @@ -1025,7 +1026,9 @@ static const struct gpio_chip adc3xxx_gpio_chip = { · 1005 unmodified lines | ||
| 1025 | 1026 | |
| 1026 | 1027 | static void adc3xxx_free_gpio(struct adc3xxx *adc3xxx) |
| 1027 | 1028 | { |
| 1029 | +#ifdef CONFIG_GPIOLIB | |
| 1028 | 1030 | gpiochip_remove(&adc3xxx->gpio_chip); |
| 1031 | +#endif | |
| 1029 | 1032 | } |
| 1030 | 1033 | |
| 1031 | 1034 | static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx) |
| @@ -2503,6 +2503,14 @@ static void wm8962_configure_bclk(struct snd_soc_component *component) · 2502 unmodified lines | ||
| 2503 | 2503 | snd_soc_component_update_bits(component, WM8962_CLOCKING2, |
| 2504 | 2504 | WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); |
| 2505 | 2505 | |
| 2506 | + /* DSPCLK_DIV field in WM8962_CLOCKING1 register is used to generate | |
| 2507 | + * correct frequency of LRCLK and BCLK. Sometimes the read-only value | |
| 2508 | + * can't be updated timely after enabling SYSCLK. This results in wrong | |
| 2509 | + * calculation values. Delay is introduced here to wait for newest | |
| 2510 | + * value from register. The time of the delay should be at least | |
| 2511 | + * 500~1000us according to test. | |
| 2512 | + */ | |
| 2513 | + usleep_range(500, 1000); | |
| 2506 | 2514 | dspclk = snd_soc_component_read(component, WM8962_CLOCKING1); |
| 2507 | 2515 | |
| 2508 | 2516 | if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON) |
| @@ -1232,7 +1232,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) · 1231 unmodified lines | ||
| 1232 | 1232 | } |
| 1233 | 1233 | |
| 1234 | 1234 | ret = pm_runtime_put_sync(&pdev->dev); |
| 1235 | − if (ret < 0) | |
| 1235 | + if (ret < 0 && ret != -ENOSYS) | |
| 1236 | 1236 | goto err_pm_get_sync; |
| 1237 | 1237 | |
| 1238 | 1238 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, |
| @@ -1069,7 +1069,7 @@ static int fsl_esai_probe(struct platform_device *pdev) · 1068 unmodified lines | ||
| 1069 | 1069 | regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0); |
| 1070 | 1070 | |
| 1071 | 1071 | ret = pm_runtime_put_sync(&pdev->dev); |
| 1072 | − if (ret < 0) | |
| 1072 | + if (ret < 0 && ret != -ENOSYS) | |
| 1073 | 1073 | goto err_pm_get_sync; |
| 1074 | 1074 | |
| 1075 | 1075 | /* |
| @@ -376,6 +376,25 @@ static int fsl_micfil_reset(struct device *dev) · 375 unmodified lines | ||
| 376 | 376 | if (ret) |
| 377 | 377 | return ret; |
| 378 | 378 | |
| 379 | + /* | |
| 380 | + * SRES is self-cleared bit, but REG_MICFIL_CTRL1 is defined | |
| 381 | + * as non-volatile register, so SRES still remain in regmap | |
| 382 | + * cache after set, that every update of REG_MICFIL_CTRL1, | |
| 383 | + * software reset happens. so clear it explicitly. | |
| 384 | + */ | |
| 385 | + ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1, | |
| 386 | + MICFIL_CTRL1_SRES); | |
| 387 | + if (ret) | |
| 388 | + return ret; | |
| 389 | + | |
| 390 | + /* | |
| 391 | + * Set SRES should clear CHnF flags, But even add delay here | |
| 392 | + * the CHnF may not be cleared sometimes, so clear CHnF explicitly. | |
| 393 | + */ | |
| 394 | + ret = regmap_write_bits(micfil->regmap, REG_MICFIL_STAT, 0xFF, 0xFF); | |
| 395 | + if (ret) | |
| 396 | + return ret; | |
| 397 | + | |
| 379 | 398 | return 0; |
| 380 | 399 | } |
| 381 | 400 | |
| @@ -1448,7 +1448,7 @@ static int fsl_sai_probe(struct platform_device *pdev) · 1447 unmodified lines | ||
| 1448 | 1448 | } |
| 1449 | 1449 | |
| 1450 | 1450 | ret = pm_runtime_put_sync(dev); |
| 1451 | − if (ret < 0) | |
| 1451 | + if (ret < 0 && ret != -ENOSYS) | |
| 1452 | 1452 | goto err_pm_get_sync; |
| 1453 | 1453 | |
| 1454 | 1454 | /* |
| @@ -443,6 +443,13 @@ static const struct dmi_system_id byt_cht_es8316_quirk_table[] = { · 442 unmodified lines | ||
| 443 | 443 | | BYT_CHT_ES8316_INTMIC_IN2_MAP |
| 444 | 444 | | BYT_CHT_ES8316_JD_INVERTED), |
| 445 | 445 | }, |
| 446 | + { /* Nanote UMPC-01 */ | |
| 447 | + .matches = { | |
| 448 | + DMI_MATCH(DMI_SYS_VENDOR, "RWC CO.,LTD"), | |
| 449 | + DMI_MATCH(DMI_PRODUCT_NAME, "UMPC-01"), | |
| 450 | + }, | |
| 451 | + .driver_data = (void *)BYT_CHT_ES8316_INTMIC_IN1_MAP, | |
| 452 | + }, | |
| 446 | 453 | { /* Teclast X98 Plus II */ |
| 447 | 454 | .matches = { |
| 448 | 455 | DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), |
| @@ -63,6 +63,7 @@ struct sof_es8336_private { · 62 unmodified lines | ||
| 63 | 63 | struct snd_soc_jack jack; |
| 64 | 64 | struct list_head hdmi_pcm_list; |
| 65 | 65 | bool speaker_en; |
| 66 | + struct delayed_work pcm_pop_work; | |
| 66 | 67 | }; |
| 67 | 68 | |
| 68 | 69 | struct sof_hdmi_pcm { |
| @@ -111,6 +112,46 @@ static void log_quirks(struct device *dev) · 42 unmodified lines | ||
| 111 | 112 | dev_info(dev, "quirk headset at mic1 port enabled\n"); |
| 112 | 113 | } |
| 113 | 114 | |
| 115 | +static void pcm_pop_work_events(struct work_struct *work) | |
| 116 | +{ | |
| 117 | + struct sof_es8336_private *priv = | |
| 118 | + container_of(work, struct sof_es8336_private, pcm_pop_work.work); | |
| 119 | + | |
| 120 | + gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en); | |
| 121 | + | |
| 122 | + if (quirk & SOF_ES8336_HEADPHONE_GPIO) | |
| 123 | + gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en); | |
| 124 | + | |
| 125 | +} | |
| 126 | + | |
| 127 | +static int sof_8336_trigger(struct snd_pcm_substream *substream, int cmd) | |
| 128 | +{ | |
| 129 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | |
| 130 | + struct snd_soc_card *card = rtd->card; | |
| 131 | + struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); | |
| 132 | + | |
| 133 | + switch (cmd) { | |
| 134 | + case SNDRV_PCM_TRIGGER_START: | |
| 135 | + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
| 136 | + case SNDRV_PCM_TRIGGER_RESUME: | |
| 137 | + break; | |
| 138 | + | |
| 139 | + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
| 140 | + case SNDRV_PCM_TRIGGER_SUSPEND: | |
| 141 | + case SNDRV_PCM_TRIGGER_STOP: | |
| 142 | + if (priv->speaker_en == false) | |
| 143 | + if (substream->stream == 0) { | |
| 144 | + cancel_delayed_work(&priv->pcm_pop_work); | |
| 145 | + gpiod_set_value_cansleep(priv->gpio_speakers, true); | |
| 146 | + } | |
| 147 | + break; | |
| 148 | + default: | |
| 149 | + return -EINVAL; | |
| 150 | + } | |
| 151 | + | |
| 152 | + return 0; | |
| 153 | +} | |
| 154 | + | |
| 114 | 155 | static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, |
| 115 | 156 | struct snd_kcontrol *kcontrol, int event) |
| 116 | 157 | { |
| @@ -122,19 +163,7 @@ static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, · 5 unmodified lines | ||
| 122 | 163 | |
| 123 | 164 | priv->speaker_en = !SND_SOC_DAPM_EVENT_ON(event); |
| 124 | 165 | |
| 125 | − if (SND_SOC_DAPM_EVENT_ON(event)) | |
| 126 | − msleep(70); | |
| 127 | − | |
| 128 | − gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en); | |
| 129 | − | |
| 130 | − if (!(quirk & SOF_ES8336_HEADPHONE_GPIO)) | |
| 131 | − return 0; | |
| 132 | − | |
| 133 | − if (SND_SOC_DAPM_EVENT_ON(event)) | |
| 134 | − msleep(70); | |
| 135 | − | |
| 136 | − gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en); | |
| 137 | − | |
| 166 | + queue_delayed_work(system_wq, &priv->pcm_pop_work, msecs_to_jiffies(70)); | |
| 138 | 167 | return 0; |
| 139 | 168 | } |
| 140 | 169 | |
| @@ -344,6 +373,7 @@ static int sof_es8336_hw_params(struct snd_pcm_substream *substream, · 203 unmodified lines | ||
| 344 | 373 | /* machine stream operations */ |
| 345 | 374 | static struct snd_soc_ops sof_es8336_ops = { |
| 346 | 375 | .hw_params = sof_es8336_hw_params, |
| 376 | + .trigger = sof_8336_trigger, | |
| 347 | 377 | }; |
| 348 | 378 | |
| 349 | 379 | static struct snd_soc_dai_link_component platform_component[] = { |
| @@ -723,7 +753,8 @@ static int sof_es8336_probe(struct platform_device *pdev) · 373 unmodified lines | ||
| 723 | 753 | } |
| 724 | 754 | |
| 725 | 755 | INIT_LIST_HEAD(&priv->hdmi_pcm_list); |
| 726 | − | |
| 756 | + INIT_DELAYED_WORK(&priv->pcm_pop_work, | |
| 757 | + pcm_pop_work_events); | |
| 727 | 758 | snd_soc_card_set_drvdata(card, priv); |
| 728 | 759 | |
| 729 | 760 | if (mach->mach_params.dmic_num > 0) { |
| @@ -752,6 +783,7 @@ static int sof_es8336_remove(struct platform_device *pdev) · 22 unmodified lines | ||
| 752 | 783 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 753 | 784 | struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); |
| 754 | 785 | |
| 786 | + cancel_delayed_work(&priv->pcm_pop_work); | |
| 755 | 787 | gpiod_put(priv->gpio_speakers); |
| 756 | 788 | device_remove_software_node(priv->codec_dev); |
| 757 | 789 | put_device(priv->codec_dev); |
| @@ -10,6 +10,11 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <sound/soc-acpi-intel-match.h> |
| 11 | 11 | #include "../skylake/skl.h" |
| 12 | 12 | |
| 13 | +static const struct snd_soc_acpi_codecs essx_83x6 = { | |
| 14 | + .num_codecs = 3, | |
| 15 | + .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, | |
| 16 | +}; | |
| 17 | + | |
| 13 | 18 | static struct skl_machine_pdata icl_pdata = { |
| 14 | 19 | .use_tplg_pcm = true, |
| 15 | 20 | }; |
| @@ -27,6 +32,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[] = { · 11 unmodified lines | ||
| 27 | 32 | .drv_name = "sof_rt5682", |
| 28 | 33 | .sof_tplg_filename = "sof-icl-rt5682.tplg", |
| 29 | 34 | }, |
| 35 | + { | |
| 36 | + .comp_ids = &essx_83x6, | |
| 37 | + .drv_name = "sof-essx8336", | |
| 38 | + .sof_tplg_filename = "sof-icl-es8336", /* the tplg suffix is added at run time */ | |
| 39 | + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER | | |
| 40 | + SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | | |
| 41 | + SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, | |
| 42 | + }, | |
| 30 | 43 | {}, |
| 31 | 44 | }; |
| 32 | 45 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_icl_machines); |
| @@ -3477,10 +3477,23 @@ EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_link_cpus); · 3476 unmodified lines | ||
| 3477 | 3477 | |
| 3478 | 3478 | static int __init snd_soc_init(void) |
| 3479 | 3479 | { |
| 3480 | + int ret; | |
| 3481 | + | |
| 3480 | 3482 | snd_soc_debugfs_init(); |
| 3481 | − snd_soc_util_init(); | |
| 3483 | + ret = snd_soc_util_init(); | |
| 3484 | + if (ret) | |
| 3485 | + goto err_util_init; | |
| 3482 | 3486 | |
| 3483 | − return platform_driver_register(&soc_driver); | |
| 3487 | + ret = platform_driver_register(&soc_driver); | |
| 3488 | + if (ret) | |
| 3489 | + goto err_register; | |
| 3490 | + return 0; | |
| 3491 | + | |
| 3492 | +err_register: | |
| 3493 | + snd_soc_util_exit(); | |
| 3494 | +err_util_init: | |
| 3495 | + snd_soc_debugfs_exit(); | |
| 3496 | + return ret; | |
| 3484 | 3497 | } |
| 3485 | 3498 | module_init(snd_soc_init); |
| 3486 | 3499 | |
| @@ -3620,7 +3620,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, · 3619 unmodified lines | ||
| 3620 | 3620 | |
| 3621 | 3621 | switch (w->id) { |
| 3622 | 3622 | case snd_soc_dapm_regulator_supply: |
| 3623 | − w->regulator = devm_regulator_get(dapm->dev, w->name); | |
| 3623 | + w->regulator = devm_regulator_get(dapm->dev, widget->name); | |
| 3624 | 3624 | if (IS_ERR(w->regulator)) { |
| 3625 | 3625 | ret = PTR_ERR(w->regulator); |
| 3626 | 3626 | goto request_failed; |
| @@ -452,7 +452,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, · 451 unmodified lines | ||
| 452 | 452 | val = ucontrol->value.integer.value[0]; |
| 453 | 453 | if (mc->platform_max && val > mc->platform_max) |
| 454 | 454 | return -EINVAL; |
| 455 | − if (val > max - min) | |
| 455 | + if (val > max) | |
| 456 | 456 | return -EINVAL; |
| 457 | 457 | val_mask = mask << shift; |
| 458 | 458 | val = (val + min) & mask; |
| @@ -464,10 +464,15 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 464 | 464 | ret = err; |
| 465 | 465 | |
| 466 | 466 | if (snd_soc_volsw_is_stereo(mc)) { |
| 467 | − unsigned int val2; | |
| 467 | + unsigned int val2 = ucontrol->value.integer.value[1]; | |
| 468 | + | |
| 469 | + if (mc->platform_max && val2 > mc->platform_max) | |
| 470 | + return -EINVAL; | |
| 471 | + if (val2 > max) | |
| 472 | + return -EINVAL; | |
| 468 | 473 | |
| 469 | 474 | val_mask = mask << rshift; |
| 470 | − val2 = (ucontrol->value.integer.value[1] + min) & mask; | |
| 475 | + val2 = (val2 + min) & mask; | |
| 471 | 476 | val2 = val2 << rshift; |
| 472 | 477 | |
| 473 | 478 | err = snd_soc_component_update_bits(component, reg2, val_mask, |
| @@ -822,11 +822,6 @@ static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd, · 821 unmodified lines | ||
| 822 | 822 | ret = snd_soc_dai_startup(dai, substream); |
| 823 | 823 | if (ret < 0) |
| 824 | 824 | goto err; |
| 825 | − | |
| 826 | − if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
| 827 | − dai->tx_mask = 0; | |
| 828 | − else | |
| 829 | − dai->rx_mask = 0; | |
| 830 | 825 | } |
| 831 | 826 | |
| 832 | 827 | /* Dynamic PCM DAI links compat checks use dynamic capabilities */ |
| @@ -1252,6 +1247,8 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, · 419 unmodified lines | ||
| 1252 | 1247 | return; |
| 1253 | 1248 | |
| 1254 | 1249 | be_substream = snd_soc_dpcm_get_substream(be, stream); |
| 1250 | + if (!be_substream) | |
| 1251 | + return; | |
| 1255 | 1252 | |
| 1256 | 1253 | for_each_dpcm_fe(be, stream, dpcm) { |
| 1257 | 1254 | if (dpcm->fe == fe) |
| @@ -2275,6 +2275,7 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif · 2274 unmodified lines | ||
| 2275 | 2275 | struct sof_ipc_fw_version *v = &sdev->fw_ready.version; |
| 2276 | 2276 | struct snd_sof_widget *swidget; |
| 2277 | 2277 | struct snd_sof_route *sroute; |
| 2278 | + bool dyn_widgets = false; | |
| 2278 | 2279 | int ret; |
| 2279 | 2280 | |
| 2280 | 2281 | /* |
| @@ -2284,12 +2285,14 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif · 3 unmodified lines | ||
| 2284 | 2285 | * topology loading the sound card unavailable to open PCMs. |
| 2285 | 2286 | */ |
| 2286 | 2287 | list_for_each_entry(swidget, &sdev->widget_list, list) { |
| 2287 | − if (swidget->dynamic_pipeline_widget) | |
| 2288 | + if (swidget->dynamic_pipeline_widget) { | |
| 2289 | + dyn_widgets = true; | |
| 2288 | 2290 | continue; |
| 2291 | + } | |
| 2289 | 2292 | |
| 2290 | − /* Do not free widgets for static pipelines with FW ABI older than 3.19 */ | |
| 2293 | + /* Do not free widgets for static pipelines with FW older than SOF2.2 */ | |
| 2291 | 2294 | if (!verify && !swidget->dynamic_pipeline_widget && |
| 2292 | − v->abi_version < SOF_ABI_VER(3, 19, 0)) { | |
| 2295 | + SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) { | |
| 2293 | 2296 | swidget->use_count = 0; |
| 2294 | 2297 | swidget->complete = 0; |
| 2295 | 2298 | continue; |
| @@ -2303,9 +2306,11 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif · 7 unmodified lines | ||
| 2303 | 2306 | /* |
| 2304 | 2307 | * Tear down all pipelines associated with PCMs that did not get suspended |
| 2305 | 2308 | * and unset the prepare flag so that they can be set up again during resume. |
| 2306 | − * Skip this step for older firmware. | |
| 2309 | + * Skip this step for older firmware unless topology has any | |
| 2310 | + * dynamic pipeline (in which case the step is mandatory). | |
| 2307 | 2311 | */ |
| 2308 | − if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) { | |
| 2312 | + if (!verify && (dyn_widgets || SOF_FW_VER(v->major, v->minor, v->micro) >= | |
| 2313 | + SOF_FW_VER(2, 2, 0))) { | |
| 2309 | 2314 | ret = sof_tear_down_left_over_pipelines(sdev); |
| 2310 | 2315 | if (ret < 0) { |
| 2311 | 2316 | dev_err(sdev->dev, "failed to tear down paused pipelines\n"); |
| @@ -1499,16 +1499,6 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, · 1498 unmodified lines | ||
| 1499 | 1499 | break; |
| 1500 | 1500 | } |
| 1501 | 1501 | |
| 1502 | − if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { | |
| 1503 | − swidget->core = SOF_DSP_PRIMARY_CORE; | |
| 1504 | − } else { | |
| 1505 | − int core = sof_get_token_value(SOF_TKN_COMP_CORE_ID, swidget->tuples, | |
| 1506 | − swidget->num_tuples); | |
| 1507 | − | |
| 1508 | − if (core >= 0) | |
| 1509 | − swidget->core = core; | |
| 1510 | − } | |
| 1511 | − | |
| 1512 | 1502 | /* check token parsing reply */ |
| 1513 | 1503 | if (ret < 0) { |
| 1514 | 1504 | dev_err(scomp->dev, |
| @@ -1520,6 +1510,16 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, · 5 unmodified lines | ||
| 1520 | 1510 | return ret; |
| 1521 | 1511 | } |
| 1522 | 1512 | |
| 1513 | + if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { | |
| 1514 | + swidget->core = SOF_DSP_PRIMARY_CORE; | |
| 1515 | + } else { | |
| 1516 | + int core = sof_get_token_value(SOF_TKN_COMP_CORE_ID, swidget->tuples, | |
| 1517 | + swidget->num_tuples); | |
| 1518 | + | |
| 1519 | + if (core >= 0) | |
| 1520 | + swidget->core = core; | |
| 1521 | + } | |
| 1522 | + | |
| 1523 | 1523 | /* bind widget to external event */ |
| 1524 | 1524 | if (tw->event_type) { |
| 1525 | 1525 | if (widget_ops[w->id].bind_event) { |
| @@ -304,6 +304,11 @@ static int stm32_adfsdm_dummy_cb(const void *data, void *private) · 303 unmodified lines | ||
| 304 | 304 | return 0; |
| 305 | 305 | } |
| 306 | 306 | |
| 307 | +static void stm32_adfsdm_cleanup(void *data) | |
| 308 | +{ | |
| 309 | + iio_channel_release_all_cb(data); | |
| 310 | +} | |
| 311 | + | |
| 307 | 312 | static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { |
| 308 | 313 | .open = stm32_adfsdm_pcm_open, |
| 309 | 314 | .close = stm32_adfsdm_pcm_close, |
| @@ -350,6 +355,12 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) · 40 unmodified lines | ||
| 350 | 355 | if (IS_ERR(priv->iio_cb)) |
| 351 | 356 | return PTR_ERR(priv->iio_cb); |
| 352 | 357 | |
| 358 | + ret = devm_add_action_or_reset(&pdev->dev, stm32_adfsdm_cleanup, priv->iio_cb); | |
| 359 | + if (ret < 0) { | |
| 360 | + dev_err(&pdev->dev, "Unable to add action\n"); | |
| 361 | + return ret; | |
| 362 | + } | |
| 363 | + | |
| 353 | 364 | component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); |
| 354 | 365 | if (!component) |
| 355 | 366 | return -ENOMEM; |
| @@ -1077,7 +1077,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, · 1076 unmodified lines | ||
| 1077 | 1077 | if (irq < 0) |
| 1078 | 1078 | return irq; |
| 1079 | 1079 | |
| 1080 | − ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, | |
| 1080 | + ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, 0, | |
| 1081 | 1081 | dev_name(&pdev->dev), i2s); |
| 1082 | 1082 | if (ret) { |
| 1083 | 1083 | dev_err(&pdev->dev, "irq request returned %d\n", ret); |