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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'sound-fix-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
"A collection of device-specific fixes that have been gathered since
the previous pull:

- A few more HD-audio quirks and fixups

- A series of Qualcomm AudioReach fixes

- Various small fixes for ASoC rt5665, WSA, SOF and Cirrus"

* tag 'sound-fix-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda/realtek: Fix built-in mic on another ASUS VivoBook model
ALSA: hda/realtek - Support mute led function for HP platform
ASoC: imx-card: Add NULL check in imx_card_probe()
ASoC: codecs: rt5665: Fix some error handling paths in rt5665_probe()
ASoC: q6apm-dai: make use of q6apm_get_hw_pointer
ASoC: qdsp6: q6apm-dai: fix capture pipeline overruns.
ASoC: qdsp6: q6apm-dai: set 10 ms period and buffer alignment.
ASoC: q6apm: add q6apm_get_hw_pointer helper
ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs
ASoC: SOF: hda/ptl: Move mic privacy change notification sending to a work
ALSA/hda: intel-sdw-acpi: Remove (explicitly) unused header
ALSA: hda/realtek: Enable Mute LED on HP OMEN 16 Laptop xd000xx
ALSA: hda/tas2781: Upgrade calibratd-data writing code to support Alpha and Beta dsp firmware
ASoC: qdsp6: q6asm-dai: fix q6asm_dai_compr_set_params error path
ALSA: hda/realtek: Fix built-in mic breakage on ASUS VivoBook X515JA
ASoC: sma1307: Fix error handling in sma1307_setting_loaded()
ASoC: codecs: wsa884x: Correct VI sense channel mask
ASoC: codecs: wsa883x: Correct VI sense channel mask
firmware: cs_dsp: Ensure cs_dsp_load[_coeff]() returns 0 on success

+205 -90
+2
drivers/firmware/cirrus/cs_dsp.c
··· 1631 1631 1632 1632 cs_dsp_debugfs_save_wmfwname(dsp, file); 1633 1633 1634 + ret = 0; 1634 1635 out_fw: 1635 1636 cs_dsp_buf_free(&buf_list); 1636 1637 ··· 2339 2338 2340 2339 cs_dsp_debugfs_save_binname(dsp, file); 2341 2340 2341 + ret = 0; 2342 2342 out_fw: 2343 2343 cs_dsp_buf_free(&buf_list); 2344 2344
+1 -1
sound/hda/intel-sdw-acpi.c
··· 11 11 #include <linux/device.h> 12 12 #include <linux/errno.h> 13 13 #include <linux/export.h> 14 - #include <linux/fwnode.h> 15 14 #include <linux/module.h> 15 + #include <linux/property.h> 16 16 #include <linux/soundwire/sdw_intel.h> 17 17 #include <linux/string.h> 18 18
+56 -9
sound/pci/hda/patch_realtek.c
··· 4743 4743 } 4744 4744 } 4745 4745 4746 + static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec, 4747 + const struct hda_fixup *fix, 4748 + int action) 4749 + { 4750 + struct alc_spec *spec = codec->spec; 4751 + 4752 + if (action == HDA_FIXUP_ACT_PRE_PROBE) { 4753 + spec->mute_led_polarity = 0; 4754 + spec->mute_led_coef.idx = 0x0b; 4755 + spec->mute_led_coef.mask = 1 << 3; 4756 + spec->mute_led_coef.on = 1 << 3; 4757 + spec->mute_led_coef.off = 0; 4758 + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); 4759 + } 4760 + } 4761 + 4746 4762 /* turn on/off mic-mute LED per capture hook by coef bit */ 4747 4763 static int coef_micmute_led_set(struct led_classdev *led_cdev, 4748 4764 enum led_brightness brightness) ··· 7590 7574 alc245_fixup_hp_gpio_led(codec, fix, action); 7591 7575 } 7592 7576 7577 + static void alc245_fixup_hp_zbook_firefly_g12a(struct hda_codec *codec, 7578 + const struct hda_fixup *fix, int action) 7579 + { 7580 + struct alc_spec *spec = codec->spec; 7581 + static const hda_nid_t conn[] = { 0x02 }; 7582 + 7583 + switch (action) { 7584 + case HDA_FIXUP_ACT_PRE_PROBE: 7585 + spec->gen.auto_mute_via_amp = 1; 7586 + snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); 7587 + break; 7588 + } 7589 + 7590 + cs35l41_fixup_i2c_two(codec, fix, action); 7591 + alc245_fixup_hp_mute_led_coefbit(codec, fix, action); 7592 + alc285_fixup_hp_coef_micmute_led(codec, fix, action); 7593 + } 7594 + 7593 7595 /* 7594 7596 * ALC287 PCM hooks 7595 7597 */ ··· 7945 7911 ALC245_FIXUP_TAS2781_SPI_2, 7946 7912 ALC287_FIXUP_YOGA7_14ARB7_I2C, 7947 7913 ALC245_FIXUP_HP_MUTE_LED_COEFBIT, 7914 + ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT, 7948 7915 ALC245_FIXUP_HP_X360_MUTE_LEDS, 7949 7916 ALC287_FIXUP_THINKPAD_I2S_SPK, 7950 7917 ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD, ··· 7956 7921 ALC256_FIXUP_HEADPHONE_AMP_VOL, 7957 7922 ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX, 7958 7923 ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX, 7924 + ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A, 7959 7925 ALC285_FIXUP_ASUS_GA403U, 7960 7926 ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC, 7961 7927 ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1, ··· 10200 10164 .type = HDA_FIXUP_FUNC, 10201 10165 .v.func = alc245_fixup_hp_mute_led_coefbit, 10202 10166 }, 10167 + [ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT] = { 10168 + .type = HDA_FIXUP_FUNC, 10169 + .v.func = alc245_fixup_hp_mute_led_v1_coefbit, 10170 + }, 10203 10171 [ALC245_FIXUP_HP_X360_MUTE_LEDS] = { 10204 10172 .type = HDA_FIXUP_FUNC, 10205 10173 .v.func = alc245_fixup_hp_mute_led_coefbit, ··· 10251 10211 [ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX] = { 10252 10212 .type = HDA_FIXUP_FUNC, 10253 10213 .v.func = alc245_fixup_hp_spectre_x360_16_aa0xxx, 10214 + }, 10215 + [ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A] = { 10216 + .type = HDA_FIXUP_FUNC, 10217 + .v.func = alc245_fixup_hp_zbook_firefly_g12a, 10254 10218 }, 10255 10219 [ALC285_FIXUP_ASUS_GA403U] = { 10256 10220 .type = HDA_FIXUP_FUNC, ··· 10702 10658 SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), 10703 10659 SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), 10704 10660 SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), 10661 + SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT), 10705 10662 SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), 10706 10663 SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), 10707 10664 SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), ··· 10796 10751 SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), 10797 10752 SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), 10798 10753 SND_PCI_QUIRK(0x103c, 0x8e13, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), 10799 - SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), 10800 - SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), 10801 - SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), 10802 - SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), 10803 - SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), 10804 - SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), 10805 - SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), 10806 - SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED), 10807 - SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED), 10754 + SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10755 + SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10756 + SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10757 + SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10758 + SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10759 + SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10760 + SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10761 + SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10762 + SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), 10808 10763 SND_PCI_QUIRK(0x103c, 0x8e2c, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED), 10809 10764 SND_PCI_QUIRK(0x103c, 0x8e36, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), 10810 10765 SND_PCI_QUIRK(0x103c, 0x8e37, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), ··· 10849 10804 SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), 10850 10805 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2), 10851 10806 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2), 10807 + SND_PCI_QUIRK(0x1043, 0x14f2, "ASUS VivoBook X515JA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), 10852 10808 SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2), 10853 10809 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), 10854 10810 SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2), ··· 10889 10843 SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), 10890 10844 SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), 10891 10845 SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), 10846 + SND_PCI_QUIRK(0x1043, 0x1c80, "ASUS VivoBook TP401", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), 10892 10847 SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), 10893 10848 SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), 10894 10849 SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
+20 -10
sound/pci/hda/tas2781_hda_i2c.c
··· 558 558 559 559 static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) 560 560 { 561 - static const unsigned char page_array[CALIB_MAX] = { 562 - 0x17, 0x18, 0x18, 0x13, 0x18, 561 + struct calidata *cali_data = &tas_priv->cali_data; 562 + struct cali_reg *r = &cali_data->cali_reg_array; 563 + unsigned int cali_reg[CALIB_MAX] = { 564 + TASDEVICE_REG(0, 0x17, 0x74), 565 + TASDEVICE_REG(0, 0x18, 0x0c), 566 + TASDEVICE_REG(0, 0x18, 0x14), 567 + TASDEVICE_REG(0, 0x13, 0x70), 568 + TASDEVICE_REG(0, 0x18, 0x7c), 563 569 }; 564 - static const unsigned char rgno_array[CALIB_MAX] = { 565 - 0x74, 0x0c, 0x14, 0x70, 0x7c, 566 - }; 567 - int offset = 0; 568 570 int i, j, rc; 571 + int oft = 0; 569 572 __be32 data; 573 + 574 + if (tas_priv->dspbin_typ != TASDEV_BASIC) { 575 + cali_reg[0] = r->r0_reg; 576 + cali_reg[1] = r->invr0_reg; 577 + cali_reg[2] = r->r0_low_reg; 578 + cali_reg[3] = r->pow_reg; 579 + cali_reg[4] = r->tlimit_reg; 580 + } 570 581 571 582 for (i = 0; i < tas_priv->ndev; i++) { 572 583 for (j = 0; j < CALIB_MAX; j++) { 573 584 data = cpu_to_be32( 574 - *(uint32_t *)&tas_priv->cali_data.data[offset]); 585 + *(uint32_t *)&tas_priv->cali_data.data[oft]); 575 586 rc = tasdevice_dev_bulk_write(tas_priv, i, 576 - TASDEVICE_REG(0, page_array[j], rgno_array[j]), 577 - (unsigned char *)&data, 4); 587 + cali_reg[j], (unsigned char *)&data, 4); 578 588 if (rc < 0) 579 589 dev_err(tas_priv->dev, 580 590 "chn %d calib %d bulk_wr err = %d\n", 581 591 i, j, rc); 582 - offset += 4; 592 + oft += 4; 583 593 } 584 594 } 585 595 }
+4 -20
sound/soc/codecs/rt5665.c
··· 31 31 #include "rl6231.h" 32 32 #include "rt5665.h" 33 33 34 - #define RT5665_NUM_SUPPLIES 3 35 - 36 - static const char *rt5665_supply_names[RT5665_NUM_SUPPLIES] = { 34 + static const char * const rt5665_supply_names[] = { 37 35 "AVDD", 38 36 "MICVDD", 39 37 "VBAT", ··· 44 46 struct gpio_desc *gpiod_ldo1_en; 45 47 struct gpio_desc *gpiod_reset; 46 48 struct snd_soc_jack *hs_jack; 47 - struct regulator_bulk_data supplies[RT5665_NUM_SUPPLIES]; 48 49 struct delayed_work jack_detect_work; 49 50 struct delayed_work calibrate_work; 50 51 struct delayed_work jd_check_work; ··· 4468 4471 struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component); 4469 4472 4470 4473 regmap_write(rt5665->regmap, RT5665_RESET, 0); 4471 - 4472 - regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies); 4473 4474 } 4474 4475 4475 4476 #ifdef CONFIG_PM ··· 4753 4758 { 4754 4759 struct rt5665_platform_data *pdata = dev_get_platdata(&i2c->dev); 4755 4760 struct rt5665_priv *rt5665; 4756 - int i, ret; 4761 + int ret; 4757 4762 unsigned int val; 4758 4763 4759 4764 rt5665 = devm_kzalloc(&i2c->dev, sizeof(struct rt5665_priv), ··· 4769 4774 else 4770 4775 rt5665_parse_dt(rt5665, &i2c->dev); 4771 4776 4772 - for (i = 0; i < ARRAY_SIZE(rt5665->supplies); i++) 4773 - rt5665->supplies[i].supply = rt5665_supply_names[i]; 4774 - 4775 - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5665->supplies), 4776 - rt5665->supplies); 4777 + ret = devm_regulator_bulk_get_enable(&i2c->dev, ARRAY_SIZE(rt5665_supply_names), 4778 + rt5665_supply_names); 4777 4779 if (ret != 0) { 4778 4780 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); 4779 4781 return ret; 4780 4782 } 4781 - 4782 - ret = regulator_bulk_enable(ARRAY_SIZE(rt5665->supplies), 4783 - rt5665->supplies); 4784 - if (ret != 0) { 4785 - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); 4786 - return ret; 4787 - } 4788 - 4789 4783 4790 4784 rt5665->gpiod_ldo1_en = devm_gpiod_get_optional(&i2c->dev, 4791 4785 "realtek,ldo1-en",
+2 -9
sound/soc/codecs/sma1307.c
··· 1705 1705 static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file) 1706 1706 { 1707 1707 const struct firmware *fw; 1708 - int *data, size, offset, num_mode; 1708 + int size, offset, num_mode; 1709 1709 int ret; 1710 1710 1711 1711 ret = request_firmware(&fw, file, sma1307->dev); ··· 1722 1722 return; 1723 1723 } 1724 1724 1725 - data = kzalloc(fw->size, GFP_KERNEL); 1725 + int *data __free(kfree) = kzalloc(fw->size, GFP_KERNEL); 1726 1726 if (!data) { 1727 1727 release_firmware(fw); 1728 1728 sma1307->set.status = false; ··· 1742 1742 sma1307->set.header_size, 1743 1743 GFP_KERNEL); 1744 1744 if (!sma1307->set.header) { 1745 - kfree(data); 1746 1745 sma1307->set.status = false; 1747 1746 return; 1748 1747 } ··· 1762 1763 = devm_kzalloc(sma1307->dev, 1763 1764 sma1307->set.def_size * sizeof(int), GFP_KERNEL); 1764 1765 if (!sma1307->set.def) { 1765 - kfree(data); 1766 - kfree(sma1307->set.header); 1767 1766 sma1307->set.status = false; 1768 1767 return; 1769 1768 } ··· 1779 1782 sma1307->set.mode_size * 2 * sizeof(int), 1780 1783 GFP_KERNEL); 1781 1784 if (!sma1307->set.mode_set[i]) { 1782 - kfree(data); 1783 - kfree(sma1307->set.header); 1784 - kfree(sma1307->set.def); 1785 1785 for (int j = 0; j < i; j++) 1786 1786 kfree(sma1307->set.mode_set[j]); 1787 1787 sma1307->set.status = false; ··· 1793 1799 } 1794 1800 } 1795 1801 1796 - kfree(data); 1797 1802 sma1307->set.status = true; 1798 1803 1799 1804 }
+1 -1
sound/soc/codecs/wsa883x.c
··· 568 568 }, 569 569 [WSA883X_PORT_VISENSE] = { 570 570 .num = WSA883X_PORT_VISENSE + 1, 571 - .ch_mask = 0x3, 571 + .ch_mask = 0x1, 572 572 }, 573 573 }; 574 574
+1 -1
sound/soc/codecs/wsa884x.c
··· 891 891 }, 892 892 [WSA884X_PORT_VISENSE] = { 893 893 .num = WSA884X_PORT_VISENSE + 1, 894 - .ch_mask = 0x3, 894 + .ch_mask = 0x1, 895 895 }, 896 896 [WSA884X_PORT_CPS] = { 897 897 .num = WSA884X_PORT_CPS + 1,
+4
sound/soc/fsl/imx-card.c
··· 772 772 data->dapm_routes[i].sink = 773 773 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", 774 774 i + 1, "Playback"); 775 + if (!data->dapm_routes[i].sink) 776 + return -ENOMEM; 775 777 data->dapm_routes[i].source = "CPU-Playback"; 776 778 } 777 779 } ··· 791 789 data->dapm_routes[i].source = 792 790 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", 793 791 i + 1, "Capture"); 792 + if (!data->dapm_routes[i].source) 793 + return -ENOMEM; 794 794 data->dapm_routes[i].sink = "CPU-Capture"; 795 795 } 796 796 }
+32 -28
sound/soc/qcom/qdsp6/q6apm-dai.c
··· 24 24 #define PLAYBACK_MIN_PERIOD_SIZE 128 25 25 #define CAPTURE_MIN_NUM_PERIODS 2 26 26 #define CAPTURE_MAX_NUM_PERIODS 8 27 - #define CAPTURE_MAX_PERIOD_SIZE 4096 28 - #define CAPTURE_MIN_PERIOD_SIZE 320 27 + #define CAPTURE_MAX_PERIOD_SIZE 65536 28 + #define CAPTURE_MIN_PERIOD_SIZE 6144 29 29 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE) 30 30 #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE) 31 31 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) ··· 64 64 phys_addr_t phys; 65 65 unsigned int pcm_size; 66 66 unsigned int pcm_count; 67 - unsigned int pos; /* Buffer position */ 68 67 unsigned int periods; 69 68 unsigned int bytes_sent; 70 69 unsigned int bytes_received; 71 70 unsigned int copied_total; 72 71 uint16_t bits_per_sample; 72 + snd_pcm_uframes_t queue_ptr; 73 73 bool next_track; 74 74 enum stream_state state; 75 75 struct q6apm_graph *graph; ··· 123 123 { 124 124 struct q6apm_dai_rtd *prtd = priv; 125 125 struct snd_pcm_substream *substream = prtd->substream; 126 - unsigned long flags; 127 126 128 127 switch (opcode) { 129 128 case APM_CLIENT_EVENT_CMD_EOS_DONE: 130 129 prtd->state = Q6APM_STREAM_STOPPED; 131 130 break; 132 131 case APM_CLIENT_EVENT_DATA_WRITE_DONE: 133 - spin_lock_irqsave(&prtd->lock, flags); 134 - prtd->pos += prtd->pcm_count; 135 - spin_unlock_irqrestore(&prtd->lock, flags); 136 132 snd_pcm_period_elapsed(substream); 137 - if (prtd->state == Q6APM_STREAM_RUNNING) 138 - q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); 139 133 140 134 break; 141 135 case APM_CLIENT_EVENT_DATA_READ_DONE: 142 - spin_lock_irqsave(&prtd->lock, flags); 143 - prtd->pos += prtd->pcm_count; 144 - spin_unlock_irqrestore(&prtd->lock, flags); 145 136 snd_pcm_period_elapsed(substream); 146 137 if (prtd->state == Q6APM_STREAM_RUNNING) 147 138 q6apm_read(prtd->graph); ··· 239 248 } 240 249 241 250 prtd->pcm_count = snd_pcm_lib_period_bytes(substream); 242 - prtd->pos = 0; 243 251 /* rate and channels are sent to audio driver */ 244 252 ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); 245 253 if (ret < 0) { ··· 284 294 return 0; 285 295 } 286 296 297 + static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) 298 + { 299 + struct snd_pcm_runtime *runtime = substream->runtime; 300 + struct q6apm_dai_rtd *prtd = runtime->private_data; 301 + int i, ret = 0, avail_periods; 302 + 303 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 304 + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; 305 + for (i = 0; i < avail_periods; i++) { 306 + ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); 307 + if (ret < 0) { 308 + dev_err(component->dev, "Error queuing playback buffer %d\n", ret); 309 + return ret; 310 + } 311 + prtd->queue_ptr += runtime->period_size; 312 + } 313 + } 314 + 315 + return ret; 316 + } 317 + 287 318 static int q6apm_dai_trigger(struct snd_soc_component *component, 288 319 struct snd_pcm_substream *substream, int cmd) 289 320 { ··· 316 305 case SNDRV_PCM_TRIGGER_START: 317 306 case SNDRV_PCM_TRIGGER_RESUME: 318 307 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 319 - /* start writing buffers for playback only as we already queued capture buffers */ 320 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 321 - ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); 322 308 break; 323 309 case SNDRV_PCM_TRIGGER_STOP: 324 310 /* TODO support be handled via SoftPause Module */ ··· 385 377 } 386 378 } 387 379 388 - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 380 + /* setup 10ms latency to accommodate DSP restrictions */ 381 + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); 389 382 if (ret < 0) { 390 383 dev_err(dev, "constraint for period bytes step ret = %d\n", ret); 391 384 goto err; 392 385 } 393 386 394 - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 387 + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); 395 388 if (ret < 0) { 396 389 dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); 397 390 goto err; ··· 437 428 struct snd_pcm_runtime *runtime = substream->runtime; 438 429 struct q6apm_dai_rtd *prtd = runtime->private_data; 439 430 snd_pcm_uframes_t ptr; 440 - unsigned long flags; 441 431 442 - spin_lock_irqsave(&prtd->lock, flags); 443 - if (prtd->pos == prtd->pcm_size) 444 - prtd->pos = 0; 432 + ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size; 433 + if (ptr) 434 + return ptr - 1; 445 435 446 - ptr = bytes_to_frames(runtime, prtd->pos); 447 - spin_unlock_irqrestore(&prtd->lock, flags); 448 - 449 - return ptr; 436 + return 0; 450 437 } 451 438 452 439 static int q6apm_dai_hw_params(struct snd_soc_component *component, ··· 657 652 prtd->pcm_size = runtime->fragments * runtime->fragment_size; 658 653 prtd->bits_per_sample = 16; 659 654 660 - prtd->pos = 0; 661 - 662 655 if (prtd->next_track != true) { 663 656 memcpy(&prtd->codec, codec, sizeof(*codec)); 664 657 ··· 839 836 .hw_params = q6apm_dai_hw_params, 840 837 .pointer = q6apm_dai_pointer, 841 838 .trigger = q6apm_dai_trigger, 839 + .ack = q6apm_dai_ack, 842 840 .compress_ops = &q6apm_dai_compress_ops, 843 841 .use_dai_pcm_id = true, 844 842 };
+17 -1
sound/soc/qcom/qdsp6/q6apm.c
··· 494 494 } 495 495 EXPORT_SYMBOL_GPL(q6apm_read); 496 496 497 + int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir) 498 + { 499 + struct audioreach_graph_data *data; 500 + 501 + if (dir == SNDRV_PCM_STREAM_PLAYBACK) 502 + data = &graph->rx_data; 503 + else 504 + data = &graph->tx_data; 505 + 506 + return (int)atomic_read(&data->hw_ptr); 507 + } 508 + EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer); 509 + 497 510 static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) 498 511 { 499 512 struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done; ··· 533 520 done = data->payload; 534 521 phys = graph->rx_data.buf[token].phys; 535 522 mutex_unlock(&graph->lock); 536 - 523 + /* token numbering starts at 0 */ 524 + atomic_set(&graph->rx_data.hw_ptr, token + 1); 537 525 if (lower_32_bits(phys) == done->buf_addr_lsw && 538 526 upper_32_bits(phys) == done->buf_addr_msw) { 539 527 graph->result.opcode = hdr->opcode; ··· 567 553 rd_done = data->payload; 568 554 phys = graph->tx_data.buf[hdr->token].phys; 569 555 mutex_unlock(&graph->lock); 556 + /* token numbering starts at 0 */ 557 + atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1); 570 558 571 559 if (upper_32_bits(phys) == rd_done->buf_addr_msw && 572 560 lower_32_bits(phys) == rd_done->buf_addr_lsw) {
+3
sound/soc/qcom/qdsp6/q6apm.h
··· 2 2 #ifndef __Q6APM_H__ 3 3 #define __Q6APM_H__ 4 4 #include <linux/types.h> 5 + #include <linux/atomic.h> 5 6 #include <linux/slab.h> 6 7 #include <linux/wait.h> 7 8 #include <linux/kernel.h> ··· 78 77 uint32_t num_periods; 79 78 uint32_t dsp_buf; 80 79 uint32_t mem_map_handle; 80 + atomic_t hw_ptr; 81 81 }; 82 82 83 83 struct audioreach_graph { ··· 152 150 int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); 153 151 int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); 154 152 int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); 153 + int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir); 155 154 #endif /* __APM_GRAPH_ */
+13 -6
sound/soc/qcom/qdsp6/q6asm-dai.c
··· 892 892 893 893 if (ret < 0) { 894 894 dev_err(dev, "q6asm_open_write failed\n"); 895 - q6asm_audio_client_free(prtd->audio_client); 896 - prtd->audio_client = NULL; 897 - return ret; 895 + goto open_err; 898 896 } 899 897 } 900 898 ··· 901 903 prtd->session_id, dir); 902 904 if (ret) { 903 905 dev_err(dev, "Stream reg failed ret:%d\n", ret); 904 - return ret; 906 + goto q6_err; 905 907 } 906 908 907 909 ret = __q6asm_dai_compr_set_codec_params(component, stream, ··· 909 911 prtd->stream_id); 910 912 if (ret) { 911 913 dev_err(dev, "codec param setup failed ret:%d\n", ret); 912 - return ret; 914 + goto q6_err; 913 915 } 914 916 915 917 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, ··· 918 920 919 921 if (ret < 0) { 920 922 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); 921 - return -ENOMEM; 923 + ret = -ENOMEM; 924 + goto q6_err; 922 925 } 923 926 924 927 prtd->state = Q6ASM_STREAM_RUNNING; 925 928 926 929 return 0; 930 + 931 + q6_err: 932 + q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); 933 + 934 + open_err: 935 + q6asm_audio_client_free(prtd->audio_client); 936 + prtd->audio_client = NULL; 937 + return ret; 927 938 } 928 939 929 940 static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component,
+8
sound/soc/sof/intel/hda-dsp.c
··· 991 991 if (!sdev->dspless_mode_selected) { 992 992 /* cancel any attempt for DSP D0I3 */ 993 993 cancel_delayed_work_sync(&hda->d0i3_work); 994 + 995 + /* Cancel the microphone privacy work if mic privacy is active */ 996 + if (hda->mic_privacy.active) 997 + cancel_work_sync(&hda->mic_privacy.work); 994 998 } 995 999 996 1000 /* stop hda controller and power dsp off */ ··· 1021 1017 if (!sdev->dspless_mode_selected) { 1022 1018 /* cancel any attempt for DSP D0I3 */ 1023 1019 cancel_delayed_work_sync(&hda->d0i3_work); 1020 + 1021 + /* Cancel the microphone privacy work if mic privacy is active */ 1022 + if (hda->mic_privacy.active) 1023 + cancel_work_sync(&hda->mic_privacy.work); 1024 1024 } 1025 1025 1026 1026 if (target_state == SOF_DSP_PM_D0) {
+4
sound/soc/sof/intel/hda.c
··· 968 968 if (sdev->dspless_mode_selected) 969 969 goto skip_disable_dsp; 970 970 971 + /* Cancel the microphone privacy work if mic privacy is active */ 972 + if (hda->mic_privacy.active) 973 + cancel_work_sync(&hda->mic_privacy.work); 974 + 971 975 /* no need to check for error as the DSP will be disabled anyway */ 972 976 if (chip && chip->power_down_dsp) 973 977 chip->power_down_dsp(sdev);
+8
sound/soc/sof/intel/hda.h
··· 487 487 SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */ 488 488 }; 489 489 490 + struct sof_ace3_mic_privacy { 491 + bool active; 492 + struct work_struct work; 493 + }; 494 + 490 495 /* represents DSP HDA controller frontend - i.e. host facing control */ 491 496 struct sof_intel_hda_dev { 492 497 bool imrboot_supported; ··· 546 541 547 542 /* Intel NHLT information */ 548 543 struct nhlt_acpi_table *nhlt; 544 + 545 + /* work queue for mic privacy state change notification sending */ 546 + struct sof_ace3_mic_privacy mic_privacy; 549 547 550 548 /* 551 549 * Pointing to the IPC message if immediate sending was not possible
+29 -4
sound/soc/sof/intel/ptl.c
··· 27 27 return hdac_bus_eml_is_mic_privacy_changed(sof_to_bus(sdev), alt, elid); 28 28 } 29 29 30 + static void sof_ptl_mic_privacy_work(struct work_struct *work) 31 + { 32 + struct sof_intel_hda_dev *hdev = container_of(work, 33 + struct sof_intel_hda_dev, 34 + mic_privacy.work); 35 + struct hdac_bus *bus = &hdev->hbus.core; 36 + struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev); 37 + bool state; 38 + 39 + /* 40 + * The microphone privacy state is only available via Soundwire shim 41 + * in PTL 42 + * The work is only scheduled on change. 43 + */ 44 + state = hdac_bus_eml_get_mic_privacy_state(bus, 1, 45 + AZX_REG_ML_LEPTR_ID_SDW); 46 + sof_ipc4_mic_privacy_state_change(sdev, state); 47 + } 48 + 30 49 static void sof_ptl_process_mic_privacy(struct snd_sof_dev *sdev, bool alt, 31 50 int elid) 32 51 { 33 - bool state; 52 + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; 34 53 35 54 if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW) 36 55 return; 37 56 38 - state = hdac_bus_eml_get_mic_privacy_state(sof_to_bus(sdev), alt, elid); 39 - 40 - sof_ipc4_mic_privacy_state_change(sdev, state); 57 + /* 58 + * Schedule the work to read the microphone privacy state and send IPC 59 + * message about the new state to the firmware 60 + */ 61 + schedule_work(&hdev->mic_privacy.work); 41 62 } 42 63 43 64 static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, 44 65 struct sof_ipc4_intel_mic_privacy_cap *caps) 45 66 { 67 + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; 46 68 u32 micpvcp; 47 69 48 70 if (!caps || !caps->capabilities_length) ··· 80 58 hdac_bus_eml_set_mic_privacy_mask(sof_to_bus(sdev), true, 81 59 AZX_REG_ML_LEPTR_ID_SDW, 82 60 PTL_MICPVCP_GET_SDW_MASK(micpvcp)); 61 + 62 + INIT_WORK(&hdev->mic_privacy.work, sof_ptl_mic_privacy_work); 63 + hdev->mic_privacy.active = true; 83 64 } 84 65 85 66 int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)