Pull sound fixes from Takashi Iwai: "A collection of device-specific fixes. It became a bit bigger than wished, but all look reasonably small and safe to apply. - A few Cirrus Logic CS35L56 and CS42L43 driver fixes - ASoC SOF fixes and workarounds - Various ASoC Intel fixes - Lots of HD-, USB-audio and AMD ACP quirks" * tag 'sound-6.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (33 commits) ALSA: usb-audio: More relaxed check of MIDI jack names ALSA: hda/realtek: fix mute/micmute LED For HP mt645 ALSA: hda/realtek: cs35l41: Fix order and duplicates in quirks table ALSA: hda/realtek: cs35l41: Fix device ID / model name ALSA: hda/realtek: cs35l41: Add internal speaker support for ASUS UM3402 with missing DSD ASoC: cs35l56: Workaround for ACPI with broken spk-id-gpios property ALSA: hda: Add Lenovo Legion 7i gen7 sound quirk ASoC: SOF: IPC3: fix message bounds on ipc ops ASoC: SOF: ipc4-pcm: Workaround for crashed firmware on system suspend ASoC: q6dsp: fix event handler prototype ASoC: SOF: Intel: pci-lnl: Change the topology path to intel/sof-ipc4-tplg ASoC: SOF: Intel: pci-tgl: Change the default paths and firmware names ASoC: amd: yc: Fix non-functional mic on Lenovo 82UU ASoC: rt5645: Add DMI quirk for inverted jack-detect on MeeGoPad T8 ASoC: rt5645: Make LattePanda board DMI match more precise ASoC: SOF: amd: Fix locking in ACP IRQ handler ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work() ASoC: Intel: cht_bsw_rt5645: Cleanup codec_name handling ASoC: Intel: Boards: Fix NULL pointer deref in BYT/CHT boards ASoC: cs35l56: Remove default from IRQ1_CFG register ...
Unified · Split
| @@ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Google SC7280-Herobrine ASoC sound card driver |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Srinivasa Rao Mandadapu <srivasam@codeaurora.org> | |
| 11 | 10 | - Judy Hsiao <judyhsiao@chromium.org> |
| 12 | 11 | |
| 13 | 12 | description: |
| @@ -142,6 +142,7 @@ struct tasdevice_priv { · 141 unmodified lines | ||
| 142 | 142 | |
| 143 | 143 | void tas2781_reset(struct tasdevice_priv *tas_dev); |
| 144 | 144 | int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, |
| 145 | + struct module *module, | |
| 145 | 146 | void (*cont)(const struct firmware *fw, void *context)); |
| 146 | 147 | struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c); |
| 147 | 148 | int tasdevice_init(struct tasdevice_priv *tas_priv); |
| @@ -156,7 +156,7 @@ config SND_HDA_SCODEC_CS35L56_I2C · 155 unmodified lines | ||
| 156 | 156 | depends on I2C |
| 157 | 157 | depends on ACPI || COMPILE_TEST |
| 158 | 158 | depends on SND_SOC |
| 159 | − select CS_DSP | |
| 159 | + select FW_CS_DSP | |
| 160 | 160 | select SND_HDA_GENERIC |
| 161 | 161 | select SND_SOC_CS35L56_SHARED |
| 162 | 162 | select SND_HDA_SCODEC_CS35L56 |
| @@ -171,7 +171,7 @@ config SND_HDA_SCODEC_CS35L56_SPI · 8 unmodified lines | ||
| 171 | 171 | depends on SPI_MASTER |
| 172 | 172 | depends on ACPI || COMPILE_TEST |
| 173 | 173 | depends on SND_SOC |
| 174 | − select CS_DSP | |
| 174 | + select FW_CS_DSP | |
| 175 | 175 | select SND_HDA_GENERIC |
| 176 | 176 | select SND_SOC_CS35L56_SHARED |
| 177 | 177 | select SND_HDA_SCODEC_CS35L56 |
| @@ -91,10 +91,12 @@ static const struct cs35l41_config cs35l41_config_table[] = { · 90 unmodified lines | ||
| 91 | 91 | { "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, |
| 92 | 92 | { "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, |
| 93 | 93 | { "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, |
| 94 | + { "10431E12", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, | |
| 94 | 95 | { "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, |
| 95 | 96 | { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, |
| 96 | 97 | { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, |
| 97 | 98 | { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, |
| 99 | + { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, | |
| 98 | 100 | { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, |
| 99 | 101 | { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, |
| 100 | 102 | { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, |
| @@ -427,10 +429,12 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { · 326 unmodified lines | ||
| 427 | 429 | { "CSC3551", "10431D1F", generic_dsd_config }, |
| 428 | 430 | { "CSC3551", "10431DA2", generic_dsd_config }, |
| 429 | 431 | { "CSC3551", "10431E02", generic_dsd_config }, |
| 432 | + { "CSC3551", "10431E12", generic_dsd_config }, | |
| 430 | 433 | { "CSC3551", "10431EE2", generic_dsd_config }, |
| 431 | 434 | { "CSC3551", "10431F12", generic_dsd_config }, |
| 432 | 435 | { "CSC3551", "10431F1F", generic_dsd_config }, |
| 433 | 436 | { "CSC3551", "10431F62", generic_dsd_config }, |
| 437 | + { "CSC3551", "17AA386F", generic_dsd_config }, | |
| 434 | 438 | { "CSC3551", "17AA38B4", generic_dsd_config }, |
| 435 | 439 | { "CSC3551", "17AA38B5", generic_dsd_config }, |
| 436 | 440 | { "CSC3551", "17AA38B6", generic_dsd_config }, |
| @@ -344,6 +344,7 @@ enum { · 343 unmodified lines | ||
| 344 | 344 | CXT_FIXUP_HP_ZBOOK_MUTE_LED, |
| 345 | 345 | CXT_FIXUP_HEADSET_MIC, |
| 346 | 346 | CXT_FIXUP_HP_MIC_NO_PRESENCE, |
| 347 | + CXT_PINCFG_SWS_JS201D, | |
| 347 | 348 | }; |
| 348 | 349 | |
| 349 | 350 | /* for hda_fixup_thinkpad_acpi() */ |
| @@ -841,6 +842,17 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = { · 491 unmodified lines | ||
| 841 | 842 | {} |
| 842 | 843 | }; |
| 843 | 844 | |
| 845 | +/* SuoWoSi/South-holding JS201D with sn6140 */ | |
| 846 | +static const struct hda_pintbl cxt_pincfg_sws_js201d[] = { | |
| 847 | + { 0x16, 0x03211040 }, /* hp out */ | |
| 848 | + { 0x17, 0x91170110 }, /* SPK/Class_D */ | |
| 849 | + { 0x18, 0x95a70130 }, /* Internal mic */ | |
| 850 | + { 0x19, 0x03a11020 }, /* Headset Mic */ | |
| 851 | + { 0x1a, 0x40f001f0 }, /* Not used */ | |
| 852 | + { 0x21, 0x40f001f0 }, /* Not used */ | |
| 853 | + {} | |
| 854 | +}; | |
| 855 | + | |
| 844 | 856 | static const struct hda_fixup cxt_fixups[] = { |
| 845 | 857 | [CXT_PINCFG_LENOVO_X200] = { |
| 846 | 858 | .type = HDA_FIXUP_PINS, |
| @@ -996,6 +1008,10 @@ static const struct hda_fixup cxt_fixups[] = { · 149 unmodified lines | ||
| 996 | 1008 | .chained = true, |
| 997 | 1009 | .chain_id = CXT_FIXUP_HEADSET_MIC, |
| 998 | 1010 | }, |
| 1011 | + [CXT_PINCFG_SWS_JS201D] = { | |
| 1012 | + .type = HDA_FIXUP_PINS, | |
| 1013 | + .v.pins = cxt_pincfg_sws_js201d, | |
| 1014 | + }, | |
| 999 | 1015 | }; |
| 1000 | 1016 | |
| 1001 | 1017 | static const struct snd_pci_quirk cxt5045_fixups[] = { |
| @@ -1069,6 +1085,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { · 67 unmodified lines | ||
| 1069 | 1085 | SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE), |
| 1070 | 1086 | SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE), |
| 1071 | 1087 | SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), |
| 1088 | + SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D), | |
| 1072 | 1089 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), |
| 1073 | 1090 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), |
| 1074 | 1091 | SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), |
| @@ -1109,6 +1126,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { · 34 unmodified lines | ||
| 1109 | 1126 | { .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" }, |
| 1110 | 1127 | { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" }, |
| 1111 | 1128 | { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" }, |
| 1129 | + { .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" }, | |
| 1112 | 1130 | {} |
| 1113 | 1131 | }; |
| 1114 | 1132 | |
| @@ -9737,7 +9737,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 9736 unmodified lines | ||
| 9737 | 9737 | SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), |
| 9738 | 9738 | SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2), |
| 9739 | 9739 | SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), |
| 9740 | + SND_PCI_QUIRK(0x1028, 0x0c0b, "Dell Oasis 14 RPL-P", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | |
| 9740 | 9741 | SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK), |
| 9742 | + SND_PCI_QUIRK(0x1028, 0x0c0e, "Dell Oasis 16", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | |
| 9741 | 9743 | SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), |
| 9742 | 9744 | SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), |
| 9743 | 9745 | SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS), |
| @@ -9928,6 +9930,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 184 unmodified lines | ||
| 9928 | 9930 | SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9929 | 9931 | SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9930 | 9932 | SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9933 | + SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | |
| 9931 | 9934 | SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), |
| 9932 | 9935 | SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9933 | 9936 | SND_PCI_QUIRK(0x103c, 0x8b43, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| @@ -9935,6 +9938,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 1 unmodified line | ||
| 9935 | 9938 | SND_PCI_QUIRK(0x103c, 0x8b45, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9936 | 9939 | SND_PCI_QUIRK(0x103c, 0x8b46, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9937 | 9940 | SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9941 | + SND_PCI_QUIRK(0x103c, 0x8b59, "HP Elite mt645 G7 Mobile Thin Client U89", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | |
| 9938 | 9942 | SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9939 | 9943 | SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9940 | 9944 | SND_PCI_QUIRK(0x103c, 0x8b63, "HP Elite Dragonfly 13.5 inch G4", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), |
| @@ -10003,6 +10007,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 62 unmodified lines | ||
| 10003 | 10007 | SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), |
| 10004 | 10008 | SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), |
| 10005 | 10009 | SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2), |
| 10010 | + SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), | |
| 10006 | 10011 | SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), |
| 10007 | 10012 | SND_PCI_QUIRK(0x1043, 0x16d3, "ASUS UX5304VA", ALC245_FIXUP_CS35L41_SPI_2), |
| 10008 | 10013 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
| @@ -10046,14 +10051,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 37 unmodified lines | ||
| 10046 | 10051 | SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), |
| 10047 | 10052 | SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2), |
| 10048 | 10053 | SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), |
| 10049 | − SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), | |
| 10050 | − SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2), | |
| 10051 | 10054 | SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), |
| 10052 | − SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), | |
| 10055 | + SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), | |
| 10053 | 10056 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), |
| 10054 | 10057 | SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), |
| 10055 | 10058 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), |
| 10056 | − SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), | |
| 10059 | + SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), | |
| 10057 | 10060 | SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), |
| 10058 | 10061 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), |
| 10059 | 10062 | SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2), |
| @@ -10260,6 +10263,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 200 unmodified lines | ||
| 10260 | 10263 | SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), |
| 10261 | 10264 | SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), |
| 10262 | 10265 | SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), |
| 10266 | + SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), | |
| 10263 | 10267 | SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), |
| 10264 | 10268 | SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C), |
| 10265 | 10269 | SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C), |
| @@ -710,7 +710,7 @@ static int tas2781_hda_bind(struct device *dev, struct device *master, · 709 unmodified lines | ||
| 710 | 710 | |
| 711 | 711 | strscpy(comps->name, dev_name(dev), sizeof(comps->name)); |
| 712 | 712 | |
| 713 | − ret = tascodec_init(tas_hda->priv, codec, tasdev_fw_ready); | |
| 713 | + ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready); | |
| 714 | 714 | if (!ret) |
| 715 | 715 | comps->playback_hook = tas2781_hda_playback_hook; |
| 716 | 716 | |
| @@ -234,6 +234,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 233 unmodified lines | ||
| 234 | 234 | DMI_MATCH(DMI_PRODUCT_NAME, "82UG"), |
| 235 | 235 | } |
| 236 | 236 | }, |
| 237 | + { | |
| 238 | + .driver_data = &acp6x_card, | |
| 239 | + .matches = { | |
| 240 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 241 | + DMI_MATCH(DMI_PRODUCT_NAME, "82UU"), | |
| 242 | + } | |
| 243 | + }, | |
| 237 | 244 | { |
| 238 | 245 | .driver_data = &acp6x_card, |
| 239 | 246 | .matches = { |
| @@ -248,6 +255,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 8 unmodified lines | ||
| 248 | 255 | DMI_MATCH(DMI_PRODUCT_NAME, "82YM"), |
| 249 | 256 | } |
| 250 | 257 | }, |
| 258 | + { | |
| 259 | + .driver_data = &acp6x_card, | |
| 260 | + .matches = { | |
| 261 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 262 | + DMI_MATCH(DMI_PRODUCT_NAME, "83AS"), | |
| 263 | + } | |
| 264 | + }, | |
| 251 | 265 | { |
| 252 | 266 | .driver_data = &acp6x_card, |
| 253 | 267 | .matches = { |
| @@ -51,7 +51,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { · 50 unmodified lines | ||
| 51 | 51 | { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, |
| 52 | 52 | { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, |
| 53 | 53 | { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, |
| 54 | − { CS35L56_IRQ1_CFG, 0x00000000 }, | |
| 55 | 54 | { CS35L56_IRQ1_MASK_1, 0x83ffffff }, |
| 56 | 55 | { CS35L56_IRQ1_MASK_2, 0xffff7fff }, |
| 57 | 56 | { CS35L56_IRQ1_MASK_4, 0xe0ffffff }, |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and |
| 6 | 6 | // Cirrus Logic International Semiconductor Ltd. |
| 7 | 7 | |
| 8 | +#include <linux/acpi.h> | |
| 8 | 9 | #include <linux/completion.h> |
| 9 | 10 | #include <linux/debugfs.h> |
| 10 | 11 | #include <linux/delay.h> |
| @@ -15,6 +16,7 @@ · 4 unmodified lines | ||
| 15 | 16 | #include <linux/module.h> |
| 16 | 17 | #include <linux/pm.h> |
| 17 | 18 | #include <linux/pm_runtime.h> |
| 19 | +#include <linux/property.h> | |
| 18 | 20 | #include <linux/regmap.h> |
| 19 | 21 | #include <linux/regulator/consumer.h> |
| 20 | 22 | #include <linux/slab.h> |
| @@ -68,63 +70,7 @@ static const char * const cs35l56_asp1_mux_control_names[] = { · 47 unmodified lines | ||
| 68 | 70 | "ASP1 TX1 Source", "ASP1 TX2 Source", "ASP1 TX3 Source", "ASP1 TX4 Source" |
| 69 | 71 | }; |
| 70 | 72 | |
| 71 | −static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, | |
| 72 | − struct snd_ctl_elem_value *ucontrol) | |
| 73 | −{ | |
| 74 | − struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 75 | − struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 76 | − struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 77 | − int index = e->shift_l; | |
| 78 | − unsigned int addr, val; | |
| 79 | − int ret; | |
| 80 | − | |
| 81 | − /* Wait for mux to be initialized */ | |
| 82 | − cs35l56_wait_dsp_ready(cs35l56); | |
| 83 | − flush_work(&cs35l56->mux_init_work); | |
| 84 | − | |
| 85 | − addr = cs35l56_asp1_mixer_regs[index]; | |
| 86 | − ret = regmap_read(cs35l56->base.regmap, addr, &val); | |
| 87 | − if (ret) | |
| 88 | − return ret; | |
| 89 | − | |
| 90 | − val &= CS35L56_ASP_TXn_SRC_MASK; | |
| 91 | − ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); | |
| 92 | − | |
| 93 | − return 0; | |
| 94 | −} | |
| 95 | − | |
| 96 | −static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, | |
| 97 | − struct snd_ctl_elem_value *ucontrol) | |
| 98 | −{ | |
| 99 | − struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 100 | − struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); | |
| 101 | − struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 102 | − struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 103 | − int item = ucontrol->value.enumerated.item[0]; | |
| 104 | − int index = e->shift_l; | |
| 105 | − unsigned int addr, val; | |
| 106 | − bool changed; | |
| 107 | − int ret; | |
| 108 | − | |
| 109 | − /* Wait for mux to be initialized */ | |
| 110 | − cs35l56_wait_dsp_ready(cs35l56); | |
| 111 | − flush_work(&cs35l56->mux_init_work); | |
| 112 | − | |
| 113 | − addr = cs35l56_asp1_mixer_regs[index]; | |
| 114 | − val = snd_soc_enum_item_to_val(e, item); | |
| 115 | − | |
| 116 | − ret = regmap_update_bits_check(cs35l56->base.regmap, addr, | |
| 117 | − CS35L56_ASP_TXn_SRC_MASK, val, &changed); | |
| 118 | − if (!ret) | |
| 119 | − return ret; | |
| 120 | − | |
| 121 | − if (changed) | |
| 122 | − snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | |
| 123 | − | |
| 124 | − return changed; | |
| 125 | −} | |
| 126 | − | |
| 127 | −static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l56) | |
| 73 | +static int cs35l56_sync_asp1_mixer_widgets_with_firmware(struct cs35l56_private *cs35l56) | |
| 128 | 74 | { |
| 129 | 75 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component); |
| 130 | 76 | const char *prefix = cs35l56->component->name_prefix; |
| @@ -135,13 +81,19 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5 · 4 unmodified lines | ||
| 135 | 81 | unsigned int val[4]; |
| 136 | 82 | int i, item, ret; |
| 137 | 83 | |
| 84 | + if (cs35l56->asp1_mixer_widgets_initialized) | |
| 85 | + return 0; | |
| 86 | + | |
| 138 | 87 | /* |
| 139 | 88 | * Resume so we can read the registers from silicon if the regmap |
| 140 | 89 | * cache has not yet been populated. |
| 141 | 90 | */ |
| 142 | 91 | ret = pm_runtime_resume_and_get(cs35l56->base.dev); |
| 143 | 92 | if (ret < 0) |
| 144 | − return; | |
| 93 | + return ret; | |
| 94 | + | |
| 95 | + /* Wait for firmware download and reboot */ | |
| 96 | + cs35l56_wait_dsp_ready(cs35l56); | |
| 145 | 97 | |
| 146 | 98 | ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, |
| 147 | 99 | val, ARRAY_SIZE(val)); |
| @@ -151,12 +103,9 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5 · 3 unmodified lines | ||
| 151 | 103 | |
| 152 | 104 | if (ret) { |
| 153 | 105 | dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret); |
| 154 | − return; | |
| 106 | + return ret; | |
| 155 | 107 | } |
| 156 | 108 | |
| 157 | − snd_soc_card_mutex_lock(dapm->card); | |
| 158 | − WARN_ON(!dapm->card->instantiated); | |
| 159 | − | |
| 160 | 109 | for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) { |
| 161 | 110 | name = cs35l56_asp1_mux_control_names[i]; |
| 162 | 111 | |
| @@ -176,16 +125,65 @@ static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l5 · 13 unmodified lines | ||
| 176 | 125 | snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); |
| 177 | 126 | } |
| 178 | 127 | |
| 179 | − snd_soc_card_mutex_unlock(dapm->card); | |
| 128 | + cs35l56->asp1_mixer_widgets_initialized = true; | |
| 129 | + | |
| 130 | + return 0; | |
| 180 | 131 | } |
| 181 | 132 | |
| 182 | −static void cs35l56_mux_init_work(struct work_struct *work) | |
| 133 | +static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, | |
| 134 | + struct snd_ctl_elem_value *ucontrol) | |
| 183 | 135 | { |
| 184 | − struct cs35l56_private *cs35l56 = container_of(work, | |
| 185 | − struct cs35l56_private, | |
| 186 | − mux_init_work); | |
| 136 | + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 137 | + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 138 | + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 139 | + int index = e->shift_l; | |
| 140 | + unsigned int addr, val; | |
| 141 | + int ret; | |
| 142 | + | |
| 143 | + ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); | |
| 144 | + if (ret) | |
| 145 | + return ret; | |
| 146 | + | |
| 147 | + addr = cs35l56_asp1_mixer_regs[index]; | |
| 148 | + ret = regmap_read(cs35l56->base.regmap, addr, &val); | |
| 149 | + if (ret) | |
| 150 | + return ret; | |
| 151 | + | |
| 152 | + val &= CS35L56_ASP_TXn_SRC_MASK; | |
| 153 | + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); | |
| 154 | + | |
| 155 | + return 0; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, | |
| 159 | + struct snd_ctl_elem_value *ucontrol) | |
| 160 | +{ | |
| 161 | + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 162 | + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); | |
| 163 | + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 164 | + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 165 | + int item = ucontrol->value.enumerated.item[0]; | |
| 166 | + int index = e->shift_l; | |
| 167 | + unsigned int addr, val; | |
| 168 | + bool changed; | |
| 169 | + int ret; | |
| 187 | 170 | |
| 188 | − cs35l56_mark_asp1_mixer_widgets_dirty(cs35l56); | |
| 171 | + ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); | |
| 172 | + if (ret) | |
| 173 | + return ret; | |
| 174 | + | |
| 175 | + addr = cs35l56_asp1_mixer_regs[index]; | |
| 176 | + val = snd_soc_enum_item_to_val(e, item); | |
| 177 | + | |
| 178 | + ret = regmap_update_bits_check(cs35l56->base.regmap, addr, | |
| 179 | + CS35L56_ASP_TXn_SRC_MASK, val, &changed); | |
| 180 | + if (ret) | |
| 181 | + return ret; | |
| 182 | + | |
| 183 | + if (changed) | |
| 184 | + snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | |
| 185 | + | |
| 186 | + return changed; | |
| 189 | 187 | } |
| 190 | 188 | |
| 191 | 189 | static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); |
| @@ -936,14 +934,6 @@ static void cs35l56_dsp_work(struct work_struct *work) · 744 unmodified lines | ||
| 936 | 934 | else |
| 937 | 935 | cs35l56_patch(cs35l56, firmware_missing); |
| 938 | 936 | |
| 939 | − | |
| 940 | − /* | |
| 941 | − * Set starting value of ASP1 mux widgets. Updating a mux takes | |
| 942 | − * the DAPM mutex. Post this to a separate job so that DAPM | |
| 943 | − * power-up can wait for dsp_work to complete without deadlocking | |
| 944 | − * on the DAPM mutex. | |
| 945 | − */ | |
| 946 | − queue_work(cs35l56->dsp_wq, &cs35l56->mux_init_work); | |
| 947 | 937 | err: |
| 948 | 938 | pm_runtime_mark_last_busy(cs35l56->base.dev); |
| 949 | 939 | pm_runtime_put_autosuspend(cs35l56->base.dev); |
| @@ -989,6 +979,13 @@ static int cs35l56_component_probe(struct snd_soc_component *component) · 39 unmodified lines | ||
| 989 | 979 | debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate); |
| 990 | 980 | debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched); |
| 991 | 981 | |
| 982 | + /* | |
| 983 | + * The widgets for the ASP1TX mixer can't be initialized | |
| 984 | + * until the firmware has been downloaded and rebooted. | |
| 985 | + */ | |
| 986 | + regcache_drop_region(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX4_INPUT); | |
| 987 | + cs35l56->asp1_mixer_widgets_initialized = false; | |
| 988 | + | |
| 992 | 989 | queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); |
| 993 | 990 | |
| 994 | 991 | return 0; |
| @@ -999,7 +996,6 @@ static void cs35l56_component_remove(struct snd_soc_component *component) · 4 unmodified lines | ||
| 999 | 996 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); |
| 1000 | 997 | |
| 1001 | 998 | cancel_work_sync(&cs35l56->dsp_work); |
| 1002 | − cancel_work_sync(&cs35l56->mux_init_work); | |
| 1003 | 999 | |
| 1004 | 1000 | if (cs35l56->dsp.cs_dsp.booted) |
| 1005 | 1001 | wm_adsp_power_down(&cs35l56->dsp); |
| @@ -1070,10 +1066,8 @@ int cs35l56_system_suspend(struct device *dev) · 64 unmodified lines | ||
| 1070 | 1066 | |
| 1071 | 1067 | dev_dbg(dev, "system_suspend\n"); |
| 1072 | 1068 | |
| 1073 | − if (cs35l56->component) { | |
| 1069 | + if (cs35l56->component) | |
| 1074 | 1070 | flush_work(&cs35l56->dsp_work); |
| 1075 | − cancel_work_sync(&cs35l56->mux_init_work); | |
| 1076 | − } | |
| 1077 | 1071 | |
| 1078 | 1072 | /* |
| 1079 | 1073 | * The interrupt line is normally shared, but after we start suspending |
| @@ -1224,7 +1218,6 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) · 144 unmodified lines | ||
| 1224 | 1218 | return -ENOMEM; |
| 1225 | 1219 | |
| 1226 | 1220 | INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); |
| 1227 | − INIT_WORK(&cs35l56->mux_init_work, cs35l56_mux_init_work); | |
| 1228 | 1221 | |
| 1229 | 1222 | dsp = &cs35l56->dsp; |
| 1230 | 1223 | cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp); |
| @@ -1269,6 +1262,94 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) · 38 unmodified lines | ||
| 1269 | 1262 | return 0; |
| 1270 | 1263 | } |
| 1271 | 1264 | |
| 1265 | +/* | |
| 1266 | + * Some SoundWire laptops have a spk-id-gpios property but it points to | |
| 1267 | + * the wrong ACPI Device node so can't be used to get the GPIO. Try to | |
| 1268 | + * find the SDCA node containing the GpioIo resource and add a GPIO | |
| 1269 | + * mapping to it. | |
| 1270 | + */ | |
| 1271 | +static const struct acpi_gpio_params cs35l56_af01_first_gpio = { 0, 0, false }; | |
| 1272 | +static const struct acpi_gpio_mapping cs35l56_af01_spkid_gpios_mapping[] = { | |
| 1273 | + { "spk-id-gpios", &cs35l56_af01_first_gpio, 1 }, | |
| 1274 | + { } | |
| 1275 | +}; | |
| 1276 | + | |
| 1277 | +static void cs35l56_acpi_dev_release_driver_gpios(void *adev) | |
| 1278 | +{ | |
| 1279 | + acpi_dev_remove_driver_gpios(adev); | |
| 1280 | +} | |
| 1281 | + | |
| 1282 | +static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l56) | |
| 1283 | +{ | |
| 1284 | + struct fwnode_handle *af01_fwnode; | |
| 1285 | + const union acpi_object *obj; | |
| 1286 | + struct gpio_desc *desc; | |
| 1287 | + int ret; | |
| 1288 | + | |
| 1289 | + /* Find the SDCA node containing the GpioIo */ | |
| 1290 | + af01_fwnode = device_get_named_child_node(cs35l56->base.dev, "AF01"); | |
| 1291 | + if (!af01_fwnode) { | |
| 1292 | + dev_dbg(cs35l56->base.dev, "No AF01 node\n"); | |
| 1293 | + return -ENOENT; | |
| 1294 | + } | |
| 1295 | + | |
| 1296 | + ret = acpi_dev_get_property(ACPI_COMPANION(cs35l56->base.dev), | |
| 1297 | + "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj); | |
| 1298 | + if (ret) { | |
| 1299 | + dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret); | |
| 1300 | + return -ENOENT; | |
| 1301 | + } | |
| 1302 | + | |
| 1303 | + /* The broken properties we can handle are a 4-element package (one GPIO) */ | |
| 1304 | + if (obj->package.count != 4) { | |
| 1305 | + dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n", | |
| 1306 | + obj->package.count); | |
| 1307 | + return -ENOENT; | |
| 1308 | + } | |
| 1309 | + | |
| 1310 | + /* Add a GPIO mapping if it doesn't already have one */ | |
| 1311 | + if (!fwnode_property_present(af01_fwnode, "spk-id-gpios")) { | |
| 1312 | + struct acpi_device *adev = to_acpi_device_node(af01_fwnode); | |
| 1313 | + | |
| 1314 | + /* | |
| 1315 | + * Can't use devm_acpi_dev_add_driver_gpios() because the | |
| 1316 | + * mapping isn't being added to the node pointed to by | |
| 1317 | + * ACPI_COMPANION(). | |
| 1318 | + */ | |
| 1319 | + ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping); | |
| 1320 | + if (ret) { | |
| 1321 | + return dev_err_probe(cs35l56->base.dev, ret, | |
| 1322 | + "Failed to add gpio mapping to AF01\n"); | |
| 1323 | + } | |
| 1324 | + | |
| 1325 | + ret = devm_add_action_or_reset(cs35l56->base.dev, | |
| 1326 | + cs35l56_acpi_dev_release_driver_gpios, | |
| 1327 | + adev); | |
| 1328 | + if (ret) | |
| 1329 | + return ret; | |
| 1330 | + | |
| 1331 | + dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n"); | |
| 1332 | + } | |
| 1333 | + | |
| 1334 | + desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL); | |
| 1335 | + if (IS_ERR(desc)) { | |
| 1336 | + ret = PTR_ERR(desc); | |
| 1337 | + return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n"); | |
| 1338 | + } | |
| 1339 | + | |
| 1340 | + ret = gpiod_get_value_cansleep(desc); | |
| 1341 | + gpiod_put(desc); | |
| 1342 | + | |
| 1343 | + if (ret < 0) { | |
| 1344 | + dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n"); | |
| 1345 | + return ret; | |
| 1346 | + } | |
| 1347 | + | |
| 1348 | + dev_info(cs35l56->base.dev, "Got spk-id from AF01\n"); | |
| 1349 | + | |
| 1350 | + return ret; | |
| 1351 | +} | |
| 1352 | + | |
| 1272 | 1353 | int cs35l56_common_probe(struct cs35l56_private *cs35l56) |
| 1273 | 1354 | { |
| 1274 | 1355 | int ret; |
| @@ -1313,6 +1394,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) · 38 unmodified lines | ||
| 1313 | 1394 | } |
| 1314 | 1395 | |
| 1315 | 1396 | ret = cs35l56_get_speaker_id(&cs35l56->base); |
| 1397 | + if (ACPI_COMPANION(cs35l56->base.dev) && cs35l56->sdw_peripheral && (ret == -ENOENT)) | |
| 1398 | + ret = cs35l56_try_get_broken_sdca_spkid_gpio(cs35l56); | |
| 1399 | + | |
| 1316 | 1400 | if ((ret < 0) && (ret != -ENOENT)) |
| 1317 | 1401 | goto err; |
| 1318 | 1402 | |
| @@ -34,7 +34,6 @@ struct cs35l56_private { · 33 unmodified lines | ||
| 34 | 34 | struct wm_adsp dsp; /* must be first member */ |
| 35 | 35 | struct cs35l56_base base; |
| 36 | 36 | struct work_struct dsp_work; |
| 37 | − struct work_struct mux_init_work; | |
| 38 | 37 | struct workqueue_struct *dsp_wq; |
| 39 | 38 | struct snd_soc_component *component; |
| 40 | 39 | struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; |
| @@ -52,6 +51,7 @@ struct cs35l56_private { · 11 unmodified lines | ||
| 52 | 51 | u8 asp_slot_count; |
| 53 | 52 | bool tdm_mode; |
| 54 | 53 | bool sysclk_set; |
| 54 | + bool asp1_mixer_widgets_initialized; | |
| 55 | 55 | u8 old_sdw_clock_scale; |
| 56 | 56 | }; |
| 57 | 57 | |
| @@ -2257,7 +2257,10 @@ static int cs42l43_codec_probe(struct platform_device *pdev) · 2256 unmodified lines | ||
| 2257 | 2257 | pm_runtime_use_autosuspend(priv->dev); |
| 2258 | 2258 | pm_runtime_set_active(priv->dev); |
| 2259 | 2259 | pm_runtime_get_noresume(priv->dev); |
| 2260 | − devm_pm_runtime_enable(priv->dev); | |
| 2260 | + | |
| 2261 | + ret = devm_pm_runtime_enable(priv->dev); | |
| 2262 | + if (ret) | |
| 2263 | + goto err_pm; | |
| 2261 | 2264 | |
| 2262 | 2265 | for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { |
| 2263 | 2266 | ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name, |
| @@ -2333,8 +2336,47 @@ static int cs42l43_codec_runtime_resume(struct device *dev) · 69 unmodified lines | ||
| 2333 | 2336 | return 0; |
| 2334 | 2337 | } |
| 2335 | 2338 | |
| 2336 | −static DEFINE_RUNTIME_DEV_PM_OPS(cs42l43_codec_pm_ops, NULL, | |
| 2337 | − cs42l43_codec_runtime_resume, NULL); | |
| 2339 | +static int cs42l43_codec_suspend(struct device *dev) | |
| 2340 | +{ | |
| 2341 | + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | |
| 2342 | + | |
| 2343 | + disable_irq(cs42l43->irq); | |
| 2344 | + | |
| 2345 | + return 0; | |
| 2346 | +} | |
| 2347 | + | |
| 2348 | +static int cs42l43_codec_suspend_noirq(struct device *dev) | |
| 2349 | +{ | |
| 2350 | + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | |
| 2351 | + | |
| 2352 | + enable_irq(cs42l43->irq); | |
| 2353 | + | |
| 2354 | + return 0; | |
| 2355 | +} | |
| 2356 | + | |
| 2357 | +static int cs42l43_codec_resume(struct device *dev) | |
| 2358 | +{ | |
| 2359 | + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | |
| 2360 | + | |
| 2361 | + enable_irq(cs42l43->irq); | |
| 2362 | + | |
| 2363 | + return 0; | |
| 2364 | +} | |
| 2365 | + | |
| 2366 | +static int cs42l43_codec_resume_noirq(struct device *dev) | |
| 2367 | +{ | |
| 2368 | + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | |
| 2369 | + | |
| 2370 | + disable_irq(cs42l43->irq); | |
| 2371 | + | |
| 2372 | + return 0; | |
| 2373 | +} | |
| 2374 | + | |
| 2375 | +static const struct dev_pm_ops cs42l43_codec_pm_ops = { | |
| 2376 | + SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) | |
| 2377 | + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq) | |
| 2378 | + RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) | |
| 2379 | +}; | |
| 2338 | 2380 | |
| 2339 | 2381 | static const struct platform_device_id cs42l43_codec_id_table[] = { |
| 2340 | 2382 | { "cs42l43-codec", }, |
| @@ -3317,6 +3317,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) · 3316 unmodified lines | ||
| 3317 | 3317 | report, SND_JACK_HEADPHONE); |
| 3318 | 3318 | snd_soc_jack_report(rt5645->mic_jack, |
| 3319 | 3319 | report, SND_JACK_MICROPHONE); |
| 3320 | + mutex_unlock(&rt5645->jd_mutex); | |
| 3320 | 3321 | return; |
| 3321 | 3322 | case 4: |
| 3322 | 3323 | val = snd_soc_component_read(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020; |
| @@ -3692,6 +3693,11 @@ static const struct rt5645_platform_data jd_mode3_monospk_platform_data = { · 369 unmodified lines | ||
| 3692 | 3693 | .mono_speaker = true, |
| 3693 | 3694 | }; |
| 3694 | 3695 | |
| 3696 | +static const struct rt5645_platform_data jd_mode3_inv_data = { | |
| 3697 | + .jd_mode = 3, | |
| 3698 | + .inv_jd1_1 = true, | |
| 3699 | +}; | |
| 3700 | + | |
| 3695 | 3701 | static const struct rt5645_platform_data jd_mode3_platform_data = { |
| 3696 | 3702 | .jd_mode = 3, |
| 3697 | 3703 | }; |
| @@ -3837,6 +3843,16 @@ static const struct dmi_system_id dmi_platform_data[] = { · 139 unmodified lines | ||
| 3837 | 3843 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), |
| 3838 | 3844 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), |
| 3839 | 3845 | DMI_EXACT_MATCH(DMI_BOARD_VERSION, "Default string"), |
| 3846 | + /* | |
| 3847 | + * Above strings are too generic, LattePanda BIOS versions for | |
| 3848 | + * all 4 hw revisions are: | |
| 3849 | + * DF-BI-7-S70CR100-* | |
| 3850 | + * DF-BI-7-S70CR110-* | |
| 3851 | + * DF-BI-7-S70CR200-* | |
| 3852 | + * LP-BS-7-S70CR700-* | |
| 3853 | + * Do a partial match for S70CR to avoid false positive matches. | |
| 3854 | + */ | |
| 3855 | + DMI_MATCH(DMI_BIOS_VERSION, "S70CR"), | |
| 3840 | 3856 | }, |
| 3841 | 3857 | .driver_data = (void *)&lattepanda_board_platform_data, |
| 3842 | 3858 | }, |
| @@ -3871,6 +3887,16 @@ static const struct dmi_system_id dmi_platform_data[] = { · 28 unmodified lines | ||
| 3871 | 3887 | }, |
| 3872 | 3888 | .driver_data = (void *)&intel_braswell_platform_data, |
| 3873 | 3889 | }, |
| 3890 | + { | |
| 3891 | + .ident = "Meegopad T08", | |
| 3892 | + .matches = { | |
| 3893 | + DMI_MATCH(DMI_SYS_VENDOR, "Default string"), | |
| 3894 | + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), | |
| 3895 | + DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), | |
| 3896 | + DMI_MATCH(DMI_BOARD_VERSION, "V1.1"), | |
| 3897 | + }, | |
| 3898 | + .driver_data = (void *)&jd_mode3_inv_data, | |
| 3899 | + }, | |
| 3874 | 3900 | { } |
| 3875 | 3901 | }; |
| 3876 | 3902 | |
| @@ -267,6 +267,7 @@ void tas2781_reset(struct tasdevice_priv *tas_dev) · 266 unmodified lines | ||
| 267 | 267 | EXPORT_SYMBOL_GPL(tas2781_reset); |
| 268 | 268 | |
| 269 | 269 | int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, |
| 270 | + struct module *module, | |
| 270 | 271 | void (*cont)(const struct firmware *fw, void *context)) |
| 271 | 272 | { |
| 272 | 273 | int ret = 0; |
| @@ -280,7 +281,7 @@ int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, · 7 unmodified lines | ||
| 280 | 281 | tas_priv->dev_name, tas_priv->ndev); |
| 281 | 282 | crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL); |
| 282 | 283 | tas_priv->codec = codec; |
| 283 | − ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, | |
| 284 | + ret = request_firmware_nowait(module, FW_ACTION_UEVENT, | |
| 284 | 285 | tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv, |
| 285 | 286 | cont); |
| 286 | 287 | if (ret) |
| @@ -566,7 +566,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) · 565 unmodified lines | ||
| 566 | 566 | { |
| 567 | 567 | struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); |
| 568 | 568 | |
| 569 | − return tascodec_init(tas_priv, codec, tasdevice_fw_ready); | |
| 569 | + return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready); | |
| 570 | 570 | } |
| 571 | 571 | |
| 572 | 572 | static void tasdevice_deinit(void *context) |
| @@ -477,6 +477,9 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) · 476 unmodified lines | ||
| 477 | 477 | return 0; |
| 478 | 478 | |
| 479 | 479 | err_i915_init: |
| 480 | + pci_free_irq(pci, 0, adev); | |
| 481 | + pci_free_irq(pci, 0, bus); | |
| 482 | + pci_free_irq_vectors(pci); | |
| 480 | 483 | pci_clear_master(pci); |
| 481 | 484 | pci_set_drvdata(pci, NULL); |
| 482 | 485 | err_acquire_irq: |
| @@ -857,7 +857,7 @@ assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcf · 856 unmodified lines | ||
| 857 | 857 | } |
| 858 | 858 | |
| 859 | 859 | /* If topology sets value don't overwrite it */ |
| 860 | − if (cfg->copier.vindex.i2s.instance) | |
| 860 | + if (cfg->copier.vindex.val) | |
| 861 | 861 | return; |
| 862 | 862 | |
| 863 | 863 | mach = dev_get_platdata(comp->card->dev); |
| @@ -241,7 +241,8 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) · 240 unmodified lines | ||
| 241 | 241 | |
| 242 | 242 | /* fix index of codec dai */ |
| 243 | 243 | for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) { |
| 244 | − if (!strcmp(byt_cht_cx2072x_dais[i].codecs->name, | |
| 244 | + if (byt_cht_cx2072x_dais[i].codecs->name && | |
| 245 | + !strcmp(byt_cht_cx2072x_dais[i].codecs->name, | |
| 245 | 246 | "i2c-14F10720:00")) { |
| 246 | 247 | dai_index = i; |
| 247 | 248 | break; |
| @@ -245,7 +245,8 @@ static int bytcht_da7213_probe(struct platform_device *pdev) · 244 unmodified lines | ||
| 245 | 245 | |
| 246 | 246 | /* fix index of codec dai */ |
| 247 | 247 | for (i = 0; i < ARRAY_SIZE(dailink); i++) { |
| 248 | − if (!strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) { | |
| 248 | + if (dailink[i].codecs->name && | |
| 249 | + !strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) { | |
| 249 | 250 | dai_index = i; |
| 250 | 251 | break; |
| 251 | 252 | } |
| @@ -546,7 +546,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) · 545 unmodified lines | ||
| 546 | 546 | |
| 547 | 547 | /* fix index of codec dai */ |
| 548 | 548 | for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) { |
| 549 | − if (!strcmp(byt_cht_es8316_dais[i].codecs->name, | |
| 549 | + if (byt_cht_es8316_dais[i].codecs->name && | |
| 550 | + !strcmp(byt_cht_es8316_dais[i].codecs->name, | |
| 550 | 551 | "i2c-ESSX8316:00")) { |
| 551 | 552 | dai_index = i; |
| 552 | 553 | break; |
| @@ -1652,7 +1652,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) · 1651 unmodified lines | ||
| 1652 | 1652 | |
| 1653 | 1653 | /* fix index of codec dai */ |
| 1654 | 1654 | for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { |
| 1655 | − if (!strcmp(byt_rt5640_dais[i].codecs->name, | |
| 1655 | + if (byt_rt5640_dais[i].codecs->name && | |
| 1656 | + !strcmp(byt_rt5640_dais[i].codecs->name, | |
| 1656 | 1657 | "i2c-10EC5640:00")) { |
| 1657 | 1658 | dai_index = i; |
| 1658 | 1659 | break; |
| @@ -910,7 +910,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) · 909 unmodified lines | ||
| 910 | 910 | |
| 911 | 911 | /* fix index of codec dai */ |
| 912 | 912 | for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { |
| 913 | − if (!strcmp(byt_rt5651_dais[i].codecs->name, | |
| 913 | + if (byt_rt5651_dais[i].codecs->name && | |
| 914 | + !strcmp(byt_rt5651_dais[i].codecs->name, | |
| 914 | 915 | "i2c-10EC5651:00")) { |
| 915 | 916 | dai_index = i; |
| 916 | 917 | break; |
| @@ -605,7 +605,8 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) · 604 unmodified lines | ||
| 605 | 605 | |
| 606 | 606 | /* find index of codec dai */ |
| 607 | 607 | for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) { |
| 608 | − if (!strcmp(byt_wm5102_dais[i].codecs->name, | |
| 608 | + if (byt_wm5102_dais[i].codecs->name && | |
| 609 | + !strcmp(byt_wm5102_dais[i].codecs->name, | |
| 609 | 610 | "wm5102-codec")) { |
| 610 | 611 | dai_index = i; |
| 611 | 612 | break; |
| @@ -40,7 +40,6 @@ struct cht_acpi_card { · 39 unmodified lines | ||
| 40 | 40 | struct cht_mc_private { |
| 41 | 41 | struct snd_soc_jack jack; |
| 42 | 42 | struct cht_acpi_card *acpi_card; |
| 43 | − char codec_name[SND_ACPI_I2C_ID_LEN]; | |
| 44 | 43 | struct clk *mclk; |
| 45 | 44 | }; |
| 46 | 45 | |
| @@ -567,14 +566,14 @@ static int snd_cht_mc_probe(struct platform_device *pdev) · 520 unmodified lines | ||
| 567 | 566 | } |
| 568 | 567 | |
| 569 | 568 | card->dev = &pdev->dev; |
| 570 | − sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id); | |
| 571 | 569 | |
| 572 | 570 | /* set correct codec name */ |
| 573 | 571 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) |
| 574 | − if (!strcmp(card->dai_link[i].codecs->name, | |
| 572 | + if (cht_dailink[i].codecs->name && | |
| 573 | + !strcmp(cht_dailink[i].codecs->name, | |
| 575 | 574 | "i2c-10EC5645:00")) { |
| 576 | − card->dai_link[i].codecs->name = drv->codec_name; | |
| 577 | 575 | dai_index = i; |
| 576 | + break; | |
| 578 | 577 | } |
| 579 | 578 | |
| 580 | 579 | /* fixup codec name based on HID */ |
| @@ -466,7 +466,8 @@ static int snd_cht_mc_probe(struct platform_device *pdev) · 465 unmodified lines | ||
| 466 | 466 | |
| 467 | 467 | /* find index of codec dai */ |
| 468 | 468 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { |
| 469 | − if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) { | |
| 469 | + if (cht_dailink[i].codecs->name && | |
| 470 | + !strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) { | |
| 470 | 471 | dai_index = i; |
| 471 | 472 | break; |
| 472 | 473 | } |
| @@ -123,7 +123,7 @@ static struct snd_pcm_hardware q6apm_dai_hardware_playback = { · 122 unmodified lines | ||
| 123 | 123 | .fifo_size = 0, |
| 124 | 124 | }; |
| 125 | 125 | |
| 126 | −static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv) | |
| 126 | +static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *priv) | |
| 127 | 127 | { |
| 128 | 128 | struct q6apm_dai_rtd *prtd = priv; |
| 129 | 129 | struct snd_pcm_substream *substream = prtd->substream; |
| @@ -157,7 +157,7 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo · 27 unmodified lines | ||
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | static void event_handler_compr(uint32_t opcode, uint32_t token, |
| 160 | − uint32_t *payload, void *priv) | |
| 160 | + void *payload, void *priv) | |
| 161 | 161 | { |
| 162 | 162 | struct q6apm_dai_rtd *prtd = priv; |
| 163 | 163 | struct snd_compr_stream *substream = prtd->cstream; |
| @@ -352,7 +352,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, · 188 unmodified lines | ||
| 352 | 352 | |
| 353 | 353 | spin_lock_init(&prtd->lock); |
| 354 | 354 | prtd->substream = substream; |
| 355 | − prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler, prtd, graph_id); | |
| 355 | + prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id); | |
| 356 | 356 | if (IS_ERR(prtd->graph)) { |
| 357 | 357 | dev_err(dev, "%s: Could not allocate memory\n", __func__); |
| 358 | 358 | ret = PTR_ERR(prtd->graph); |
| @@ -496,7 +496,7 @@ static int q6apm_dai_compr_open(struct snd_soc_component *component, · 137 unmodified lines | ||
| 496 | 496 | return -ENOMEM; |
| 497 | 497 | |
| 498 | 498 | prtd->cstream = stream; |
| 499 | − prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler_compr, prtd, graph_id); | |
| 499 | + prtd->graph = q6apm_graph_open(dev, event_handler_compr, prtd, graph_id); | |
| 500 | 500 | if (IS_ERR(prtd->graph)) { |
| 501 | 501 | ret = PTR_ERR(prtd->graph); |
| 502 | 502 | kfree(prtd); |
| @@ -188,11 +188,13 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) · 187 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write); |
| 190 | 190 | if (dsp_ack) { |
| 191 | + spin_lock_irq(&sdev->ipc_lock); | |
| 191 | 192 | /* handle immediate reply from DSP core */ |
| 192 | 193 | acp_dsp_ipc_get_reply(sdev); |
| 193 | 194 | snd_sof_ipc_reply(sdev, 0); |
| 194 | 195 | /* set the done bit */ |
| 195 | 196 | acp_dsp_ipc_dsp_done(sdev); |
| 197 | + spin_unlock_irq(&sdev->ipc_lock); | |
| 196 | 198 | ipc_irq = true; |
| 197 | 199 | } |
| 198 | 200 | |
| @@ -355,21 +355,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context) · 354 unmodified lines | ||
| 355 | 355 | unsigned int count = ACP_HW_SEM_RETRY_COUNT; |
| 356 | 356 | |
| 357 | 357 | spin_lock_irq(&sdev->ipc_lock); |
| 358 | − while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { | |
| 359 | − /* Wait until acquired HW Semaphore lock or timeout */ | |
| 360 | − count--; | |
| 361 | − if (!count) { | |
| 362 | − dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); | |
| 363 | − spin_unlock_irq(&sdev->ipc_lock); | |
| 364 | − return IRQ_NONE; | |
| 365 | − } | |
| 358 | + /* Wait until acquired HW Semaphore lock or timeout */ | |
| 359 | + while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset) && --count) | |
| 360 | + ; | |
| 361 | + spin_unlock_irq(&sdev->ipc_lock); | |
| 362 | + | |
| 363 | + if (!count) { | |
| 364 | + dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); | |
| 365 | + return IRQ_NONE; | |
| 366 | 366 | } |
| 367 | 367 | |
| 368 | 368 | sof_ops(sdev)->irq_thread(irq, sdev); |
| 369 | 369 | /* Unlock or Release HW Semaphore */ |
| 370 | 370 | snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0); |
| 371 | 371 | |
| 372 | − spin_unlock_irq(&sdev->ipc_lock); | |
| 373 | 372 | return IRQ_HANDLED; |
| 374 | 373 | }; |
| 375 | 374 | |
| @@ -36,7 +36,7 @@ static const struct sof_dev_desc lnl_desc = { · 35 unmodified lines | ||
| 36 | 36 | [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl", |
| 37 | 37 | }, |
| 38 | 38 | .default_tplg_path = { |
| 39 | − [SOF_IPC_TYPE_4] = "intel/sof-ace-tplg", | |
| 39 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 40 | 40 | }, |
| 41 | 41 | .default_fw_filename = { |
| 42 | 42 | [SOF_IPC_TYPE_4] = "sof-lnl.ri", |
| @@ -33,18 +33,18 @@ static const struct sof_dev_desc tgl_desc = { · 32 unmodified lines | ||
| 33 | 33 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 34 | 34 | .default_fw_path = { |
| 35 | 35 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 36 | − [SOF_IPC_TYPE_4] = "intel/avs/tgl", | |
| 36 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl", | |
| 37 | 37 | }, |
| 38 | 38 | .default_lib_path = { |
| 39 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/tgl", | |
| 39 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl", | |
| 40 | 40 | }, |
| 41 | 41 | .default_tplg_path = { |
| 42 | 42 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 43 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 43 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 44 | 44 | }, |
| 45 | 45 | .default_fw_filename = { |
| 46 | 46 | [SOF_IPC_TYPE_3] = "sof-tgl.ri", |
| 47 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 47 | + [SOF_IPC_TYPE_4] = "sof-tgl.ri", | |
| 48 | 48 | }, |
| 49 | 49 | .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", |
| 50 | 50 | .ops = &sof_tgl_ops, |
| @@ -66,18 +66,18 @@ static const struct sof_dev_desc tglh_desc = { · 15 unmodified lines | ||
| 66 | 66 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 67 | 67 | .default_fw_path = { |
| 68 | 68 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 69 | − [SOF_IPC_TYPE_4] = "intel/avs/tgl-h", | |
| 69 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl-h", | |
| 70 | 70 | }, |
| 71 | 71 | .default_lib_path = { |
| 72 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/tgl-h", | |
| 72 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl-h", | |
| 73 | 73 | }, |
| 74 | 74 | .default_tplg_path = { |
| 75 | 75 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 76 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 76 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 77 | 77 | }, |
| 78 | 78 | .default_fw_filename = { |
| 79 | 79 | [SOF_IPC_TYPE_3] = "sof-tgl-h.ri", |
| 80 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 80 | + [SOF_IPC_TYPE_4] = "sof-tgl-h.ri", | |
| 81 | 81 | }, |
| 82 | 82 | .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", |
| 83 | 83 | .ops = &sof_tgl_ops, |
| @@ -98,18 +98,18 @@ static const struct sof_dev_desc ehl_desc = { · 14 unmodified lines | ||
| 98 | 98 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 99 | 99 | .default_fw_path = { |
| 100 | 100 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 101 | − [SOF_IPC_TYPE_4] = "intel/avs/ehl", | |
| 101 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/ehl", | |
| 102 | 102 | }, |
| 103 | 103 | .default_lib_path = { |
| 104 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/ehl", | |
| 104 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/ehl", | |
| 105 | 105 | }, |
| 106 | 106 | .default_tplg_path = { |
| 107 | 107 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 108 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 108 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 109 | 109 | }, |
| 110 | 110 | .default_fw_filename = { |
| 111 | 111 | [SOF_IPC_TYPE_3] = "sof-ehl.ri", |
| 112 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 112 | + [SOF_IPC_TYPE_4] = "sof-ehl.ri", | |
| 113 | 113 | }, |
| 114 | 114 | .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", |
| 115 | 115 | .ops = &sof_tgl_ops, |
| @@ -131,18 +131,18 @@ static const struct sof_dev_desc adls_desc = { · 15 unmodified lines | ||
| 131 | 131 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 132 | 132 | .default_fw_path = { |
| 133 | 133 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 134 | − [SOF_IPC_TYPE_4] = "intel/avs/adl-s", | |
| 134 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-s", | |
| 135 | 135 | }, |
| 136 | 136 | .default_lib_path = { |
| 137 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/adl-s", | |
| 137 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-s", | |
| 138 | 138 | }, |
| 139 | 139 | .default_tplg_path = { |
| 140 | 140 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 141 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 141 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 142 | 142 | }, |
| 143 | 143 | .default_fw_filename = { |
| 144 | 144 | [SOF_IPC_TYPE_3] = "sof-adl-s.ri", |
| 145 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 145 | + [SOF_IPC_TYPE_4] = "sof-adl-s.ri", | |
| 146 | 146 | }, |
| 147 | 147 | .nocodec_tplg_filename = "sof-adl-nocodec.tplg", |
| 148 | 148 | .ops = &sof_tgl_ops, |
| @@ -164,18 +164,18 @@ static const struct sof_dev_desc adl_desc = { · 15 unmodified lines | ||
| 164 | 164 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 165 | 165 | .default_fw_path = { |
| 166 | 166 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 167 | − [SOF_IPC_TYPE_4] = "intel/avs/adl", | |
| 167 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl", | |
| 168 | 168 | }, |
| 169 | 169 | .default_lib_path = { |
| 170 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/adl", | |
| 170 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl", | |
| 171 | 171 | }, |
| 172 | 172 | .default_tplg_path = { |
| 173 | 173 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 174 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 174 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 175 | 175 | }, |
| 176 | 176 | .default_fw_filename = { |
| 177 | 177 | [SOF_IPC_TYPE_3] = "sof-adl.ri", |
| 178 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 178 | + [SOF_IPC_TYPE_4] = "sof-adl.ri", | |
| 179 | 179 | }, |
| 180 | 180 | .nocodec_tplg_filename = "sof-adl-nocodec.tplg", |
| 181 | 181 | .ops = &sof_tgl_ops, |
| @@ -197,18 +197,18 @@ static const struct sof_dev_desc adl_n_desc = { · 15 unmodified lines | ||
| 197 | 197 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 198 | 198 | .default_fw_path = { |
| 199 | 199 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 200 | − [SOF_IPC_TYPE_4] = "intel/avs/adl-n", | |
| 200 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-n", | |
| 201 | 201 | }, |
| 202 | 202 | .default_lib_path = { |
| 203 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/adl-n", | |
| 203 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-n", | |
| 204 | 204 | }, |
| 205 | 205 | .default_tplg_path = { |
| 206 | 206 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 207 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 207 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 208 | 208 | }, |
| 209 | 209 | .default_fw_filename = { |
| 210 | 210 | [SOF_IPC_TYPE_3] = "sof-adl-n.ri", |
| 211 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 211 | + [SOF_IPC_TYPE_4] = "sof-adl-n.ri", | |
| 212 | 212 | }, |
| 213 | 213 | .nocodec_tplg_filename = "sof-adl-nocodec.tplg", |
| 214 | 214 | .ops = &sof_tgl_ops, |
| @@ -230,18 +230,18 @@ static const struct sof_dev_desc rpls_desc = { · 15 unmodified lines | ||
| 230 | 230 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 231 | 231 | .default_fw_path = { |
| 232 | 232 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 233 | − [SOF_IPC_TYPE_4] = "intel/avs/rpl-s", | |
| 233 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl-s", | |
| 234 | 234 | }, |
| 235 | 235 | .default_lib_path = { |
| 236 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/rpl-s", | |
| 236 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl-s", | |
| 237 | 237 | }, |
| 238 | 238 | .default_tplg_path = { |
| 239 | 239 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 240 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 240 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 241 | 241 | }, |
| 242 | 242 | .default_fw_filename = { |
| 243 | 243 | [SOF_IPC_TYPE_3] = "sof-rpl-s.ri", |
| 244 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 244 | + [SOF_IPC_TYPE_4] = "sof-rpl-s.ri", | |
| 245 | 245 | }, |
| 246 | 246 | .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", |
| 247 | 247 | .ops = &sof_tgl_ops, |
| @@ -263,18 +263,18 @@ static const struct sof_dev_desc rpl_desc = { · 15 unmodified lines | ||
| 263 | 263 | .dspless_mode_supported = true, /* Only supported for HDaudio */ |
| 264 | 264 | .default_fw_path = { |
| 265 | 265 | [SOF_IPC_TYPE_3] = "intel/sof", |
| 266 | − [SOF_IPC_TYPE_4] = "intel/avs/rpl", | |
| 266 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl", | |
| 267 | 267 | }, |
| 268 | 268 | .default_lib_path = { |
| 269 | − [SOF_IPC_TYPE_4] = "intel/avs-lib/rpl", | |
| 269 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl", | |
| 270 | 270 | }, |
| 271 | 271 | .default_tplg_path = { |
| 272 | 272 | [SOF_IPC_TYPE_3] = "intel/sof-tplg", |
| 273 | − [SOF_IPC_TYPE_4] = "intel/avs-tplg", | |
| 273 | + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | |
| 274 | 274 | }, |
| 275 | 275 | .default_fw_filename = { |
| 276 | 276 | [SOF_IPC_TYPE_3] = "sof-rpl.ri", |
| 277 | − [SOF_IPC_TYPE_4] = "dsp_basefw.bin", | |
| 277 | + [SOF_IPC_TYPE_4] = "sof-rpl.ri", | |
| 278 | 278 | }, |
| 279 | 279 | .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", |
| 280 | 280 | .ops = &sof_tgl_ops, |
| @@ -2360,27 +2360,16 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) · 2359 unmodified lines | ||
| 2360 | 2360 | return 0; |
| 2361 | 2361 | } |
| 2362 | 2362 | |
| 2363 | −/* | |
| 2364 | − * For older firmware, this function doesn't free widgets for static pipelines during suspend. | |
| 2365 | − * It only resets use_count for all widgets. | |
| 2366 | − */ | |
| 2367 | −static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) | |
| 2363 | +static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler, | |
| 2364 | + bool *dyn_widgets, bool verify) | |
| 2368 | 2365 | { |
| 2369 | 2366 | struct sof_ipc_fw_version *v = &sdev->fw_ready.version; |
| 2370 | 2367 | struct snd_sof_widget *swidget; |
| 2371 | − struct snd_sof_route *sroute; | |
| 2372 | − bool dyn_widgets = false; | |
| 2373 | 2368 | int ret; |
| 2374 | 2369 | |
| 2375 | − /* | |
| 2376 | − * This function is called during suspend and for one-time topology verification during | |
| 2377 | − * first boot. In both cases, there is no need to protect swidget->use_count and | |
| 2378 | − * sroute->setup because during suspend all running streams are suspended and during | |
| 2379 | − * topology loading the sound card unavailable to open PCMs. | |
| 2380 | − */ | |
| 2381 | 2370 | list_for_each_entry(swidget, &sdev->widget_list, list) { |
| 2382 | 2371 | if (swidget->dynamic_pipeline_widget) { |
| 2383 | − dyn_widgets = true; | |
| 2372 | + *dyn_widgets = true; | |
| 2384 | 2373 | continue; |
| 2385 | 2374 | } |
| 2386 | 2375 | |
| @@ -2395,11 +2384,49 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif · 8 unmodified lines | ||
| 2395 | 2384 | continue; |
| 2396 | 2385 | } |
| 2397 | 2386 | |
| 2387 | + if (include_scheduler && swidget->id != snd_soc_dapm_scheduler) | |
| 2388 | + continue; | |
| 2389 | + | |
| 2390 | + if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler) | |
| 2391 | + continue; | |
| 2392 | + | |
| 2398 | 2393 | ret = sof_widget_free(sdev, swidget); |
| 2399 | 2394 | if (ret < 0) |
| 2400 | 2395 | return ret; |
| 2401 | 2396 | } |
| 2402 | 2397 | |
| 2398 | + return 0; | |
| 2399 | +} | |
| 2400 | + | |
| 2401 | +/* | |
| 2402 | + * For older firmware, this function doesn't free widgets for static pipelines during suspend. | |
| 2403 | + * It only resets use_count for all widgets. | |
| 2404 | + */ | |
| 2405 | +static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) | |
| 2406 | +{ | |
| 2407 | + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; | |
| 2408 | + struct snd_sof_widget *swidget; | |
| 2409 | + struct snd_sof_route *sroute; | |
| 2410 | + bool dyn_widgets = false; | |
| 2411 | + int ret; | |
| 2412 | + | |
| 2413 | + /* | |
| 2414 | + * This function is called during suspend and for one-time topology verification during | |
| 2415 | + * first boot. In both cases, there is no need to protect swidget->use_count and | |
| 2416 | + * sroute->setup because during suspend all running streams are suspended and during | |
| 2417 | + * topology loading the sound card unavailable to open PCMs. Do not free the scheduler | |
| 2418 | + * widgets yet so that the secondary cores do not get powered down before all the widgets | |
| 2419 | + * associated with the scheduler are freed. | |
| 2420 | + */ | |
| 2421 | + ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify); | |
| 2422 | + if (ret < 0) | |
| 2423 | + return ret; | |
| 2424 | + | |
| 2425 | + /* free all the scheduler widgets now */ | |
| 2426 | + ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); | |
| 2427 | + if (ret < 0) | |
| 2428 | + return ret; | |
| 2429 | + | |
| 2403 | 2430 | /* |
| 2404 | 2431 | * Tear down all pipelines associated with PCMs that did not get suspended |
| 2405 | 2432 | * and unset the prepare flag so that they can be set up again during resume. |
| @@ -1067,7 +1067,7 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) · 1066 unmodified lines | ||
| 1067 | 1067 | return; |
| 1068 | 1068 | } |
| 1069 | 1069 | |
| 1070 | − if (hdr.size < sizeof(hdr)) { | |
| 1070 | + if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) { | |
| 1071 | 1071 | dev_err(sdev->dev, "The received message size is invalid\n"); |
| 1072 | 1072 | return; |
| 1073 | 1073 | } |
| @@ -413,7 +413,18 @@ skip_pause_transition: · 412 unmodified lines | ||
| 413 | 413 | ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list); |
| 414 | 414 | if (ret < 0) { |
| 415 | 415 | dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state); |
| 416 | − goto free; | |
| 416 | + /* | |
| 417 | + * workaround: if the firmware is crashed while setting the | |
| 418 | + * pipelines to reset state we must ignore the error code and | |
| 419 | + * reset it to 0. | |
| 420 | + * Since the firmware is crashed we will not send IPC messages | |
| 421 | + * and we are going to see errors printed, but the state of the | |
| 422 | + * widgets will be correct for the next boot. | |
| 423 | + */ | |
| 424 | + if (sdev->fw_state != SOF_FW_CRASHED || state != SOF_IPC4_PIPE_RESET) | |
| 425 | + goto free; | |
| 426 | + | |
| 427 | + ret = 0; | |
| 417 | 428 | } |
| 418 | 429 | |
| 419 | 430 | /* update RUNNING/RESET state for all pipelines that were just triggered */ |
| @@ -1742,50 +1742,44 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, · 1741 unmodified lines | ||
| 1742 | 1742 | } |
| 1743 | 1743 | } |
| 1744 | 1744 | |
| 1745 | −static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor( | |
| 1746 | − struct usb_host_interface *hostif, uint8_t jack_id) | |
| 1745 | +/* return iJack for the corresponding jackID */ | |
| 1746 | +static int find_usb_ijack(struct usb_host_interface *hostif, uint8_t jack_id) | |
| 1747 | 1747 | { |
| 1748 | 1748 | unsigned char *extra = hostif->extra; |
| 1749 | 1749 | int extralen = hostif->extralen; |
| 1750 | + struct usb_descriptor_header *h; | |
| 1751 | + struct usb_midi_out_jack_descriptor *outjd; | |
| 1752 | + struct usb_midi_in_jack_descriptor *injd; | |
| 1753 | + size_t sz; | |
| 1750 | 1754 | |
| 1751 | 1755 | while (extralen > 4) { |
| 1752 | − struct usb_midi_in_jack_descriptor *injd = | |
| 1753 | − (struct usb_midi_in_jack_descriptor *)extra; | |
| 1756 | + h = (struct usb_descriptor_header *)extra; | |
| 1757 | + if (h->bDescriptorType != USB_DT_CS_INTERFACE) | |
| 1758 | + goto next; | |
| 1754 | 1759 | |
| 1760 | + outjd = (struct usb_midi_out_jack_descriptor *)h; | |
| 1761 | + if (h->bLength >= sizeof(*outjd) && | |
| 1762 | + outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK && | |
| 1763 | + outjd->bJackID == jack_id) { | |
| 1764 | + sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins); | |
| 1765 | + if (outjd->bLength < sz) | |
| 1766 | + goto next; | |
| 1767 | + return *(extra + sz - 1); | |
| 1768 | + } | |
| 1769 | + | |
| 1770 | + injd = (struct usb_midi_in_jack_descriptor *)h; | |
| 1755 | 1771 | if (injd->bLength >= sizeof(*injd) && |
| 1756 | − injd->bDescriptorType == USB_DT_CS_INTERFACE && | |
| 1757 | 1772 | injd->bDescriptorSubtype == UAC_MIDI_IN_JACK && |
| 1758 | − injd->bJackID == jack_id) | |
| 1759 | − return injd; | |
| 1760 | − if (!extra[0]) | |
| 1761 | − break; | |
| 1762 | − extralen -= extra[0]; | |
| 1763 | − extra += extra[0]; | |
| 1764 | − } | |
| 1765 | − return NULL; | |
| 1766 | −} | |
| 1767 | − | |
| 1768 | −static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor( | |
| 1769 | − struct usb_host_interface *hostif, uint8_t jack_id) | |
| 1770 | −{ | |
| 1771 | − unsigned char *extra = hostif->extra; | |
| 1772 | − int extralen = hostif->extralen; | |
| 1773 | + injd->bJackID == jack_id) | |
| 1774 | + return injd->iJack; | |
| 1773 | 1775 | |
| 1774 | − while (extralen > 4) { | |
| 1775 | − struct usb_midi_out_jack_descriptor *outjd = | |
| 1776 | − (struct usb_midi_out_jack_descriptor *)extra; | |
| 1777 | − | |
| 1778 | − if (outjd->bLength >= sizeof(*outjd) && | |
| 1779 | − outjd->bDescriptorType == USB_DT_CS_INTERFACE && | |
| 1780 | − outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK && | |
| 1781 | − outjd->bJackID == jack_id) | |
| 1782 | − return outjd; | |
| 1776 | +next: | |
| 1783 | 1777 | if (!extra[0]) |
| 1784 | 1778 | break; |
| 1785 | 1779 | extralen -= extra[0]; |
| 1786 | 1780 | extra += extra[0]; |
| 1787 | 1781 | } |
| 1788 | − return NULL; | |
| 1782 | + return 0; | |
| 1789 | 1783 | } |
| 1790 | 1784 | |
| 1791 | 1785 | static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, |
| @@ -1796,13 +1790,10 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, · 4 unmodified lines | ||
| 1796 | 1790 | const char *name_format; |
| 1797 | 1791 | struct usb_interface *intf; |
| 1798 | 1792 | struct usb_host_interface *hostif; |
| 1799 | − struct usb_midi_in_jack_descriptor *injd; | |
| 1800 | − struct usb_midi_out_jack_descriptor *outjd; | |
| 1801 | 1793 | uint8_t jack_name_buf[32]; |
| 1802 | 1794 | uint8_t *default_jack_name = "MIDI"; |
| 1803 | 1795 | uint8_t *jack_name = default_jack_name; |
| 1804 | 1796 | uint8_t iJack; |
| 1805 | − size_t sz; | |
| 1806 | 1797 | int res; |
| 1807 | 1798 | |
| 1808 | 1799 | struct snd_rawmidi_substream *substream = |
| @@ -1816,21 +1807,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, · 7 unmodified lines | ||
| 1816 | 1807 | intf = umidi->iface; |
| 1817 | 1808 | if (intf && jack_id >= 0) { |
| 1818 | 1809 | hostif = intf->cur_altsetting; |
| 1819 | − iJack = 0; | |
| 1820 | − if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) { | |
| 1821 | − /* in jacks connect to outs */ | |
| 1822 | − outjd = find_usb_out_jack_descriptor(hostif, jack_id); | |
| 1823 | − if (outjd) { | |
| 1824 | − sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins); | |
| 1825 | − if (outjd->bLength >= sz) | |
| 1826 | − iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t)); | |
| 1827 | − } | |
| 1828 | − } else { | |
| 1829 | − /* and out jacks connect to ins */ | |
| 1830 | − injd = find_usb_in_jack_descriptor(hostif, jack_id); | |
| 1831 | − if (injd) | |
| 1832 | − iJack = injd->iJack; | |
| 1833 | − } | |
| 1810 | + iJack = find_usb_ijack(hostif, jack_id); | |
| 1834 | 1811 | if (iJack != 0) { |
| 1835 | 1812 | res = usb_string(umidi->dev, iJack, jack_name_buf, |
| 1836 | 1813 | ARRAY_SIZE(jack_name_buf)); |