Pull sound fixes from Takashi Iwai: "Still a bit higher amount than wished, but nothing looks really scary, and all changes are about nice and smooth device-specific fixes. - HD-audio quirks, one revert for a regression and another oneliner - AMD ACP quirks - Fixes for SDCA interrupt handling - A few Intel SOF, avs and NVL fixes - Fixes for TAS2552 DT, NAU8325, and STM32" * tag 'sound-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ASoC: amd: acp: update DMI quirk and add ACP DMIC for Lenovo platforms ASoC: SDCA: Unregister IRQ handlers on module remove ASoC: SDCA: mask Function_Status value ASoC: SDCA: Fix overwritten var within for loop ASoC: stm32_sai: fix incorrect BCLK polarity for DSP_A/B, LEFT_J ASoC: SOF: Intel: hda: modify period size constraints for ACE4 ALSA: hda/intel: enforce stricter period-size alignment for Intel NVL ASoC: nau8325: Add software reset during probe Revert "ALSA: hda/realtek: Add quirk for Gigabyte Technology to fix headphone" ASoC: Intel: avs: Fix memory leak in avs_register_i2s_test_boards() ASoC: SOF: Intel: fix iteration in is_endpoint_present() ASoC: SOF: Intel: Fix endpoint index if endpoints are missing ASoC: SDCA: Fix errors in IRQ cleanup ASoC: amd: acp: add Lenovo P16s G5 AMD quirk for legacy SDW machine ASoC: dt-bindings: ti,tas2552: Add sound-dai-cells ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IAH10
Unified · Split
| @@ -12,8 +12,8 @@ maintainers: · 11 unmodified lines | |||
| 12 | - Baojun Xu <baojun.xu@ti.com> | 12 | - Baojun Xu <baojun.xu@ti.com> |
| 13 | 13 | ||
| 14 | description: > | 14 | description: > |
| 15 | The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or | 15 | The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or |
| 16 | use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, | 16 | use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, |
| 17 | the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK. | 17 | the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK. |
| 18 | 18 | ||
| 19 | For system integration the dt-bindings/sound/tas2552.h header file provides | 19 | For system integration the dt-bindings/sound/tas2552.h header file provides |
| @@ -34,6 +34,9 @@ properties: · 14 unmodified lines | |||
| 34 | maxItems: 1 | 34 | maxItems: 1 |
| 35 | description: gpio pin to enable/disable the device | 35 | description: gpio pin to enable/disable the device |
| 36 | 36 | ||
| 37 | '#sound-dai-cells': | ||
| 38 | const: 0 | ||
| 39 | |||
| 37 | required: | 40 | required: |
| 38 | - compatible | 41 | - compatible |
| 39 | - reg | 42 | - reg |
| @@ -41,7 +44,10 @@ required: · 1 unmodified line | |||
| 41 | - iovdd-supply | 44 | - iovdd-supply |
| 42 | - avdd-supply | 45 | - avdd-supply |
| 43 | 46 | ||
| 44 | additionalProperties: false | 47 | allOf: |
| 48 | - $ref: dai-common.yaml# | ||
| 49 | |||
| 50 | unevaluatedProperties: false | ||
| 45 | 51 | ||
| 46 | examples: | 52 | examples: |
| 47 | - | | 53 | - | |
| @@ -54,6 +60,7 @@ examples: · 6 unmodified lines | |||
| 54 | audio-codec@41 { | 60 | audio-codec@41 { |
| 55 | compatible = "ti,tas2552"; | 61 | compatible = "ti,tas2552"; |
| 56 | reg = <0x41>; | 62 | reg = <0x41>; |
| 63 | #sound-dai-cells = <0>; | ||
| 57 | vbat-supply = <®_vbat>; | 64 | vbat-supply = <®_vbat>; |
| 58 | iovdd-supply = <®_iovdd>; | 65 | iovdd-supply = <®_iovdd>; |
| 59 | avdd-supply = <®_avdd>; | 66 | avdd-supply = <®_avdd>; |
| @@ -69,6 +69,8 @@ struct sdca_interrupt_info { · 68 unmodified lines | |||
| 69 | int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info, | 69 | int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info, |
| 70 | int sdca_irq, const char *name, irq_handler_t handler, | 70 | int sdca_irq, const char *name, irq_handler_t handler, |
| 71 | void *data); | 71 | void *data); |
| 72 | void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *interrupt_info, | ||
| 73 | int sdca_irq, const char *name, void *data); | ||
| 72 | int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap, | 74 | int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap, |
| 73 | struct snd_soc_component *component, | 75 | struct snd_soc_component *component, |
| 74 | struct sdca_function_data *function, | 76 | struct sdca_function_data *function, |
| @@ -81,6 +83,9 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap, · 6 unmodified lines | |||
| 81 | int sdca_irq_populate(struct sdca_function_data *function, | 83 | int sdca_irq_populate(struct sdca_function_data *function, |
| 82 | struct snd_soc_component *component, | 84 | struct snd_soc_component *component, |
| 83 | struct sdca_interrupt_info *info); | 85 | struct sdca_interrupt_info *info); |
| 86 | void sdca_irq_cleanup(struct device *dev, | ||
| 87 | struct sdca_function_data *function, | ||
| 88 | struct sdca_interrupt_info *info); | ||
| 84 | struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, | 89 | struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, |
| 85 | struct regmap *regmap, int irq); | 90 | struct regmap *regmap, int irq); |
| 86 | 91 | ||
| @@ -7680,6 +7680,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 7679 unmodified lines | |||
| 7680 | SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C), | 7680 | SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C), |
| 7681 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), | 7681 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| 7682 | SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), | 7682 | SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), |
| 7683 | SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), | ||
| 7683 | SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC), | 7684 | SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC), |
| 7684 | SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), | 7685 | SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), |
| 7685 | SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C), | 7686 | SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C), |
| @@ -313,7 +313,6 @@ enum { · 312 unmodified lines | |||
| 313 | ALC897_FIXUP_HEADSET_MIC_PIN2, | 313 | ALC897_FIXUP_HEADSET_MIC_PIN2, |
| 314 | ALC897_FIXUP_UNIS_H3C_X500S, | 314 | ALC897_FIXUP_UNIS_H3C_X500S, |
| 315 | ALC897_FIXUP_HEADSET_MIC_PIN3, | 315 | ALC897_FIXUP_HEADSET_MIC_PIN3, |
| 316 | ALC897_FIXUP_H610M_HP_PIN, | ||
| 317 | }; | 316 | }; |
| 318 | 317 | ||
| 319 | static const struct hda_fixup alc662_fixups[] = { | 318 | static const struct hda_fixup alc662_fixups[] = { |
| @@ -767,13 +766,6 @@ static const struct hda_fixup alc662_fixups[] = { · 447 unmodified lines | |||
| 767 | { } | 766 | { } |
| 768 | }, | 767 | }, |
| 769 | }, | 768 | }, |
| 770 | [ALC897_FIXUP_H610M_HP_PIN] = { | ||
| 771 | .type = HDA_FIXUP_PINS, | ||
| 772 | .v.pins = (const struct hda_pintbl[]) { | ||
| 773 | { 0x19, 0x0321403f }, /* HP out */ | ||
| 774 | { } | ||
| 775 | }, | ||
| 776 | }, | ||
| 777 | }; | 769 | }; |
| 778 | 770 | ||
| 779 | static const struct hda_quirk alc662_fixup_tbl[] = { | 771 | static const struct hda_quirk alc662_fixup_tbl[] = { |
| @@ -823,7 +815,6 @@ static const struct hda_quirk alc662_fixup_tbl[] = { · 43 unmodified lines | |||
| 823 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | 815 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
| 824 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | 816 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), |
| 825 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), | 817 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), |
| 826 | SND_PCI_QUIRK(0x1458, 0xa194, "H610M H V2 DDR4", ALC897_FIXUP_H610M_HP_PIN), | ||
| 827 | SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), | 818 | SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), |
| 828 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), | 819 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), |
| 829 | SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN), | 820 | SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN), |
| @@ -295,6 +295,9 @@ enum { · 294 unmodified lines | |||
| 295 | #define AZX_DCAPS_INTEL_LNL \ | 295 | #define AZX_DCAPS_INTEL_LNL \ |
| 296 | (AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS) | 296 | (AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS) |
| 297 | 297 | ||
| 298 | #define AZX_DCAPS_INTEL_NVL \ | ||
| 299 | (AZX_DCAPS_INTEL_LNL & ~AZX_DCAPS_NO_ALIGN_BUFSIZE) | ||
| 300 | |||
| 298 | /* quirks for ATI SB / AMD Hudson */ | 301 | /* quirks for ATI SB / AMD Hudson */ |
| 299 | #define AZX_DCAPS_PRESET_ATI_SB \ | 302 | #define AZX_DCAPS_PRESET_ATI_SB \ |
| 300 | (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\ | 303 | (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\ |
| @@ -2565,8 +2568,8 @@ static const struct pci_device_id azx_ids[] = { · 2264 unmodified lines | |||
| 2565 | /* Wildcat Lake */ | 2568 | /* Wildcat Lake */ |
| 2566 | { PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, | 2569 | { PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, |
| 2567 | /* Nova Lake */ | 2570 | /* Nova Lake */ |
| 2568 | { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, | 2571 | { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) }, |
| 2569 | { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, | 2572 | { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) }, |
| 2570 | /* Apollolake (Broxton-P) */ | 2573 | /* Apollolake (Broxton-P) */ |
| 2571 | { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, | 2574 | { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, |
| 2572 | /* Gemini-Lake */ | 2575 | /* Gemini-Lake */ |
| @@ -99,17 +99,33 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = { · 98 unmodified lines | |||
| 99 | .callback = soc_sdw_quirk_cb, | 99 | .callback = soc_sdw_quirk_cb, |
| 100 | .matches = { | 100 | .matches = { |
| 101 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 101 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 102 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YW"), | 102 | DMI_MATCH(DMI_PRODUCT_SKU, "21YW"), |
| 103 | }, | 103 | }, |
| 104 | .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), | 104 | .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), |
| 105 | }, | 105 | }, |
| 106 | { | 106 | { |
| 107 | .callback = soc_sdw_quirk_cb, | 107 | .callback = soc_sdw_quirk_cb, |
| 108 | .matches = { | 108 | .matches = { |
| 109 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 109 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 110 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YX"), | 110 | DMI_MATCH(DMI_PRODUCT_SKU, "21YX"), |
| 111 | }, | 111 | }, |
| 112 | .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), | 112 | .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), |
| 113 | }, | ||
| 114 | { | ||
| 115 | .callback = soc_sdw_quirk_cb, | ||
| 116 | .matches = { /* Lenovo P16s G5 AMD */ | ||
| 117 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 118 | DMI_MATCH(DMI_PRODUCT_SKU, "21XG"), | ||
| 119 | }, | ||
| 120 | .driver_data = (void *)(ASOC_SDW_ACP_DMIC), | ||
| 121 | }, | ||
| 122 | { | ||
| 123 | .callback = soc_sdw_quirk_cb, | ||
| 124 | .matches = { /* Lenovo P16s G5 AMD */ | ||
| 125 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 126 | DMI_MATCH(DMI_PRODUCT_SKU, "21XH"), | ||
| 127 | }, | ||
| 128 | .driver_data = (void *)(ASOC_SDW_ACP_DMIC), | ||
| 113 | }, | 129 | }, |
| 114 | { | 130 | { |
| 115 | .callback = soc_sdw_quirk_cb, | 131 | .callback = soc_sdw_quirk_cb, |
| @@ -142,7 +142,7 @@ static bool nau8325_readable_reg(struct device *dev, unsigned int reg) · 141 unmodified lines | |||
| 142 | static bool nau8325_writeable_reg(struct device *dev, unsigned int reg) | 142 | static bool nau8325_writeable_reg(struct device *dev, unsigned int reg) |
| 143 | { | 143 | { |
| 144 | switch (reg) { | 144 | switch (reg) { |
| 145 | case NAU8325_R00_HARDWARE_RST: | 145 | case NAU8325_R00_HARDWARE_RST ... NAU8325_R01_SOFTWARE_RST: |
| 146 | case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS: | 146 | case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS: |
| 147 | case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: | 147 | case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: |
| 148 | case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: | 148 | case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: |
| @@ -670,6 +670,12 @@ static void nau8325_reset_chip(struct regmap *regmap) · 521 unmodified lines | |||
| 670 | regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000); | 670 | regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000); |
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | static void nau8325_software_reset(struct regmap *regmap) | ||
| 674 | { | ||
| 675 | regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); | ||
| 676 | regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); | ||
| 677 | } | ||
| 678 | |||
| 673 | static void nau8325_init_regs(struct nau8325 *nau8325) | 679 | static void nau8325_init_regs(struct nau8325 *nau8325) |
| 674 | { | 680 | { |
| 675 | struct regmap *regmap = nau8325->regmap; | 681 | struct regmap *regmap = nau8325->regmap; |
| @@ -856,6 +862,7 @@ static int nau8325_i2c_probe(struct i2c_client *i2c) · 180 unmodified lines | |||
| 856 | nau8325_print_device_properties(nau8325); | 862 | nau8325_print_device_properties(nau8325); |
| 857 | 863 | ||
| 858 | nau8325_reset_chip(nau8325->regmap); | 864 | nau8325_reset_chip(nau8325->regmap); |
| 865 | nau8325_software_reset(nau8325->regmap); | ||
| 859 | ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value); | 866 | ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value); |
| 860 | if (ret) { | 867 | if (ret) { |
| 861 | dev_dbg(dev, "Failed to read device id (%d)", ret); | 868 | dev_dbg(dev, "Failed to read device id (%d)", ret); |
| @@ -520,7 +520,8 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) · 519 unmodified lines | |||
| 520 | if (num_elems > max_ssps) { | 520 | if (num_elems > max_ssps) { |
| 521 | dev_err(adev->dev, "board supports only %d SSP, %d specified\n", | 521 | dev_err(adev->dev, "board supports only %d SSP, %d specified\n", |
| 522 | max_ssps, num_elems); | 522 | max_ssps, num_elems); |
| 523 | return -EINVAL; | 523 | ret = -EINVAL; |
| 524 | goto exit; | ||
| 524 | } | 525 | } |
| 525 | 526 | ||
| 526 | for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { | 527 | for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { |
| @@ -528,11 +529,13 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) · 1 unmodified line | |||
| 528 | for_each_set_bit(tdm_slot, &tdm_slots, 16) { | 529 | for_each_set_bit(tdm_slot, &tdm_slots, 16) { |
| 529 | ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); | 530 | ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); |
| 530 | if (ret) | 531 | if (ret) |
| 531 | return ret; | 532 | goto exit; |
| 532 | } | 533 | } |
| 533 | } | 534 | } |
| 534 | 535 | ||
| 535 | return 0; | 536 | exit: |
| 537 | kfree(array); | ||
| 538 | return ret; | ||
| 536 | } | 539 | } |
| 537 | 540 | ||
| 538 | static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) | 541 | static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) |
| @@ -198,6 +198,14 @@ static int class_function_component_probe(struct snd_soc_component *component) · 197 unmodified lines | |||
| 198 | return sdca_irq_populate(drv->function, component, core->irq_info); | 198 | return sdca_irq_populate(drv->function, component, core->irq_info); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | static void class_function_component_remove(struct snd_soc_component *component) | ||
| 202 | { | ||
| 203 | struct class_function_drv *drv = snd_soc_component_get_drvdata(component); | ||
| 204 | struct sdca_class_drv *core = drv->core; | ||
| 205 | |||
| 206 | sdca_irq_cleanup(component->dev, drv->function, core->irq_info); | ||
| 207 | } | ||
| 208 | |||
| 201 | static int class_function_set_jack(struct snd_soc_component *component, | 209 | static int class_function_set_jack(struct snd_soc_component *component, |
| 202 | struct snd_soc_jack *jack, void *d) | 210 | struct snd_soc_jack *jack, void *d) |
| 203 | { | 211 | { |
| @@ -209,6 +217,7 @@ static int class_function_set_jack(struct snd_soc_component *component, · 5 unmodified lines | |||
| 209 | 217 | ||
| 210 | static const struct snd_soc_component_driver class_function_component_drv = { | 218 | static const struct snd_soc_component_driver class_function_component_drv = { |
| 211 | .probe = class_function_component_probe, | 219 | .probe = class_function_component_probe, |
| 220 | .remove = class_function_component_remove, | ||
| 212 | .endianness = 1, | 221 | .endianness = 1, |
| 213 | }; | 222 | }; |
| 214 | 223 | ||
| @@ -402,6 +411,13 @@ static int class_function_probe(struct auxiliary_device *auxdev, · 187 unmodified lines | |||
| 402 | return 0; | 411 | return 0; |
| 403 | } | 412 | } |
| 404 | 413 | ||
| 414 | static void class_function_remove(struct auxiliary_device *auxdev) | ||
| 415 | { | ||
| 416 | struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); | ||
| 417 | |||
| 418 | sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info); | ||
| 419 | } | ||
| 420 | |||
| 405 | static int class_function_runtime_suspend(struct device *dev) | 421 | static int class_function_runtime_suspend(struct device *dev) |
| 406 | { | 422 | { |
| 407 | struct auxiliary_device *auxdev = to_auxiliary_dev(dev); | 423 | struct auxiliary_device *auxdev = to_auxiliary_dev(dev); |
| @@ -550,6 +566,7 @@ static struct auxiliary_driver class_function_drv = { · 142 unmodified lines | |||
| 550 | }, | 566 | }, |
| 551 | 567 | ||
| 552 | .probe = class_function_probe, | 568 | .probe = class_function_probe, |
| 569 | .remove = class_function_remove, | ||
| 553 | .id_table = class_function_id_table | 570 | .id_table = class_function_id_table |
| 554 | }; | 571 | }; |
| 555 | module_auxiliary_driver(class_function_drv); | 572 | module_auxiliary_driver(class_function_drv); |
| @@ -117,9 +117,7 @@ static irqreturn_t function_status_handler(int irq, void *data) · 116 unmodified lines | |||
| 117 | 117 | ||
| 118 | status = val; | 118 | status = val; |
| 119 | for_each_set_bit(mask, &status, BITS_PER_BYTE) { | 119 | for_each_set_bit(mask, &status, BITS_PER_BYTE) { |
| 120 | mask = 1 << mask; | 120 | switch (BIT(mask)) { |
| 121 | |||
| 122 | switch (mask) { | ||
| 123 | case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION: | 121 | case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION: |
| 124 | //FIXME: Add init writes | 122 | //FIXME: Add init writes |
| 125 | break; | 123 | break; |
| @@ -140,7 +138,7 @@ static irqreturn_t function_status_handler(int irq, void *data) · 14 unmodified lines | |||
| 140 | } | 138 | } |
| 141 | } | 139 | } |
| 142 | 140 | ||
| 143 | ret = regmap_write(interrupt->function_regmap, reg, val); | 141 | ret = regmap_write(interrupt->function_regmap, reg, val & 0x7F); |
| 144 | if (ret < 0) { | 142 | if (ret < 0) { |
| 145 | dev_err(dev, "failed to clear function status: %d\n", ret); | 143 | dev_err(dev, "failed to clear function status: %d\n", ret); |
| 146 | goto error; | 144 | goto error; |
| @@ -252,8 +250,7 @@ static int sdca_irq_request_locked(struct device *dev, · 105 unmodified lines | |||
| 252 | if (irq < 0) | 250 | if (irq < 0) |
| 253 | return irq; | 251 | return irq; |
| 254 | 252 | ||
| 255 | ret = devm_request_threaded_irq(dev, irq, NULL, handler, | 253 | ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data); |
| 256 | IRQF_ONESHOT, name, data); | ||
| 257 | if (ret) | 254 | if (ret) |
| 258 | return ret; | 255 | return ret; |
| 259 | 256 | ||
| @@ -264,6 +261,22 @@ static int sdca_irq_request_locked(struct device *dev, · 4 unmodified lines | |||
| 264 | return 0; | 261 | return 0; |
| 265 | } | 262 | } |
| 266 | 263 | ||
| 264 | static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info, | ||
| 265 | int sdca_irq, const char *name, void *data) | ||
| 266 | { | ||
| 267 | int irq; | ||
| 268 | |||
| 269 | irq = regmap_irq_get_virq(info->irq_data, sdca_irq); | ||
| 270 | if (irq < 0) | ||
| 271 | return; | ||
| 272 | |||
| 273 | free_irq(irq, data); | ||
| 274 | |||
| 275 | info->irqs[sdca_irq].irq = 0; | ||
| 276 | |||
| 277 | dev_dbg(dev, "freed irq %d for %s\n", irq, name); | ||
| 278 | } | ||
| 279 | |||
| 267 | /** | 280 | /** |
| 268 | * sdca_irq_request - request an individual SDCA interrupt | 281 | * sdca_irq_request - request an individual SDCA interrupt |
| 269 | * @dev: Pointer to the struct device against which things should be allocated. | 282 | * @dev: Pointer to the struct device against which things should be allocated. |
| @@ -302,6 +315,30 @@ int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info, · 32 unmodified lines | |||
| 302 | } | 315 | } |
| 303 | EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); | 316 | EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); |
| 304 | 317 | ||
| 318 | /** | ||
| 319 | * sdca_irq_free - free an individual SDCA interrupt | ||
| 320 | * @dev: Pointer to the struct device. | ||
| 321 | * @info: Pointer to the interrupt information structure. | ||
| 322 | * @sdca_irq: SDCA interrupt position. | ||
| 323 | * @name: Name to be given to the IRQ. | ||
| 324 | * @data: Private data pointer that will be passed to the handler. | ||
| 325 | * | ||
| 326 | * Typically this is handled internally by sdca_irq_cleanup, however if | ||
| 327 | * a device requires custom IRQ handling this can be called manually before | ||
| 328 | * calling sdca_irq_cleanup, which will then skip that IRQ whilst processing. | ||
| 329 | */ | ||
| 330 | void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info, | ||
| 331 | int sdca_irq, const char *name, void *data) | ||
| 332 | { | ||
| 333 | if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) | ||
| 334 | return; | ||
| 335 | |||
| 336 | guard(mutex)(&info->irq_lock); | ||
| 337 | |||
| 338 | sdca_irq_free_locked(dev, info, sdca_irq, name, data); | ||
| 339 | } | ||
| 340 | EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA"); | ||
| 341 | |||
| 305 | /** | 342 | /** |
| 306 | * sdca_irq_data_populate - Populate common interrupt data | 343 | * sdca_irq_data_populate - Populate common interrupt data |
| 307 | * @dev: Pointer to the Function device. | 344 | * @dev: Pointer to the Function device. |
| @@ -328,8 +365,8 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap, · 20 unmodified lines | |||
| 328 | if (!dev) | 365 | if (!dev) |
| 329 | return -ENODEV; | 366 | return -ENODEV; |
| 330 | 367 | ||
| 331 | name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name, | 368 | name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name, |
| 332 | entity->label, control->label); | 369 | entity->label, control->label); |
| 333 | if (!name) | 370 | if (!name) |
| 334 | return -ENOMEM; | 371 | return -ENOMEM; |
| 335 | 372 | ||
| @@ -516,6 +553,35 @@ int sdca_irq_populate(struct sdca_function_data *function, · 180 unmodified lines | |||
| 516 | } | 553 | } |
| 517 | EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); | 554 | EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); |
| 518 | 555 | ||
| 556 | /** | ||
| 557 | * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function | ||
| 558 | * @sdev: Device pointer against which the sdca_interrupt_info was allocated. | ||
| 559 | * @function: Pointer to the SDCA Function. | ||
| 560 | * @info: Pointer to the SDCA interrupt info for this device. | ||
| 561 | * | ||
| 562 | * Typically this would be called from the driver for a single SDCA Function. | ||
| 563 | */ | ||
| 564 | void sdca_irq_cleanup(struct device *dev, | ||
| 565 | struct sdca_function_data *function, | ||
| 566 | struct sdca_interrupt_info *info) | ||
| 567 | { | ||
| 568 | int i; | ||
| 569 | |||
| 570 | guard(mutex)(&info->irq_lock); | ||
| 571 | |||
| 572 | for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { | ||
| 573 | struct sdca_interrupt *interrupt = &info->irqs[i]; | ||
| 574 | |||
| 575 | if (interrupt->function != function || !interrupt->irq) | ||
| 576 | continue; | ||
| 577 | |||
| 578 | sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); | ||
| 579 | |||
| 580 | kfree(interrupt->name); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA"); | ||
| 584 | |||
| 519 | /** | 585 | /** |
| 520 | * sdca_irq_allocate - allocate an SDCA interrupt structure for a device | 586 | * sdca_irq_allocate - allocate an SDCA interrupt structure for a device |
| 521 | * @sdev: Device pointer against which things should be allocated. | 587 | * @sdev: Device pointer against which things should be allocated. |
| @@ -219,6 +219,7 @@ EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON"); · 218 unmodified lines | |||
| 219 | int hda_dsp_pcm_open(struct snd_sof_dev *sdev, | 219 | int hda_dsp_pcm_open(struct snd_sof_dev *sdev, |
| 220 | struct snd_pcm_substream *substream) | 220 | struct snd_pcm_substream *substream) |
| 221 | { | 221 | { |
| 222 | const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); | ||
| 222 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); | 223 | struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); |
| 223 | struct snd_pcm_runtime *runtime = substream->runtime; | 224 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 224 | struct snd_soc_component *scomp = sdev->component; | 225 | struct snd_soc_component *scomp = sdev->component; |
| @@ -268,8 +269,17 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, · 43 unmodified lines | |||
| 268 | return -ENODEV; | 269 | return -ENODEV; |
| 269 | } | 270 | } |
| 270 | 271 | ||
| 271 | /* minimum as per HDA spec */ | 272 | /* |
| 272 | snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); | 273 | * Set period size constraint to ensure BDLE buffer length and |
| 274 | * start address alignment requirements are met. Align to 128 | ||
| 275 | * bytes for newer Intel platforms, with older ones using 4 byte alignment. | ||
| 276 | */ | ||
| 277 | if (chip_info->hw_ip_version >= SOF_INTEL_ACE_4_0) | ||
| 278 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
| 279 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); | ||
| 280 | else | ||
| 281 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
| 282 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); | ||
| 273 | 283 | ||
| 274 | /* avoid circular buffer wrap in middle of period */ | 284 | /* avoid circular buffer wrap in middle of period */ |
| 275 | snd_pcm_hw_constraint_integer(substream->runtime, | 285 | snd_pcm_hw_constraint_integer(substream->runtime, |
| @@ -1133,8 +1133,7 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev, · 1132 unmodified lines | |||
| 1133 | 1133 | ||
| 1134 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) | 1134 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) |
| 1135 | 1135 | ||
| 1136 | static bool is_endpoint_present(struct sdw_slave *sdw_device, | 1136 | static bool is_endpoint_present(struct sdw_slave *sdw_device, int dai_type) |
| 1137 | struct asoc_sdw_codec_info *dai_info, int dai_type) | ||
| 1138 | { | 1137 | { |
| 1139 | int i; | 1138 | int i; |
| 1140 | 1139 | ||
| @@ -1145,7 +1144,7 @@ static bool is_endpoint_present(struct sdw_slave *sdw_device, · 4 unmodified lines | |||
| 1145 | } | 1144 | } |
| 1146 | 1145 | ||
| 1147 | for (i = 0; i < sdw_device->sdca_data.num_functions; i++) { | 1146 | for (i = 0; i < sdw_device->sdca_data.num_functions; i++) { |
| 1148 | if (dai_type == dai_info->dais[i].dai_type) | 1147 | if (dai_type == asoc_sdw_get_dai_type(sdw_device->sdca_data.function[i].type)) |
| 1149 | return true; | 1148 | return true; |
| 1150 | } | 1149 | } |
| 1151 | dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type); | 1150 | dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type); |
| @@ -1199,11 +1198,10 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, · 47 unmodified lines | |||
| 1199 | } | 1198 | } |
| 1200 | for (j = 0; j < codec_info_list[i].dai_num; j++) { | 1199 | for (j = 0; j < codec_info_list[i].dai_num; j++) { |
| 1201 | /* Check if the endpoint is present by the SDCA DisCo table */ | 1200 | /* Check if the endpoint is present by the SDCA DisCo table */ |
| 1202 | if (!is_endpoint_present(sdw_device, &codec_info_list[i], | 1201 | if (!is_endpoint_present(sdw_device, codec_info_list[i].dais[j].dai_type)) |
| 1203 | codec_info_list[i].dais[j].dai_type)) | ||
| 1204 | continue; | 1202 | continue; |
| 1205 | 1203 | ||
| 1206 | endpoints[ep_index].num = ep_index; | 1204 | endpoints[ep_index].num = j; |
| 1207 | if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) { | 1205 | if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) { |
| 1208 | /* Assume all amp are aggregated */ | 1206 | /* Assume all amp are aggregated */ |
| 1209 | endpoints[ep_index].aggregated = 1; | 1207 | endpoints[ep_index].aggregated = 1; |
| @@ -802,6 +802,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) · 801 unmodified lines | |||
| 802 | break; | 802 | break; |
| 803 | /* Left justified */ | 803 | /* Left justified */ |
| 804 | case SND_SOC_DAIFMT_MSB: | 804 | case SND_SOC_DAIFMT_MSB: |
| 805 | cr1 |= SAI_XCR1_CKSTR; | ||
| 805 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; | 806 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; |
| 806 | break; | 807 | break; |
| 807 | /* Right justified */ | 808 | /* Right justified */ |
| @@ -809,9 +810,11 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) · 1 unmodified line | |||
| 809 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; | 810 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; |
| 810 | break; | 811 | break; |
| 811 | case SND_SOC_DAIFMT_DSP_A: | 812 | case SND_SOC_DAIFMT_DSP_A: |
| 813 | cr1 |= SAI_XCR1_CKSTR; | ||
| 812 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF; | 814 | frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF; |
| 813 | break; | 815 | break; |
| 814 | case SND_SOC_DAIFMT_DSP_B: | 816 | case SND_SOC_DAIFMT_DSP_B: |
| 817 | cr1 |= SAI_XCR1_CKSTR; | ||
| 815 | frcr |= SAI_XFRCR_FSPOL; | 818 | frcr |= SAI_XFRCR_FSPOL; |
| 816 | break; | 819 | break; |
| 817 | default: | 820 | default: |