mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-18 22:14:16 +00:00 
			
		
		
		
	sound fixes for 6.8-rc5
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 -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmXPayMOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE8wnhAAvJIP/ZCsVnOKkTPcns9shxcI8zaFKWOdOOny mfL2M44glIxbcdUBDM2Ic1MX2lK6WVpDDXo+leAbbITLN985MFFwhg/NzS7QbEQu ZRi28Keubbh2zqPzBOajiS1s10ELlQtiIGGEHccspElMEesitNqu0Hmd4NSWnTCX iTsx4JwDQiiO1cOdanJ7134Jngp6q05nFVM3Y47wmqYLkP9z9/2hCRsq8scZ2f40 Blc7oEfqT10HFqXCqVZsHbLioDC03eCD9AoiUkkqDb/Hz21wemmyeiXT4OmbAIFp ritzPz1RpeJhsOURyiE3KM2kQluh+JBK5Rq3eJ1tmxJbIWEAwbYRXs+yRHr2i6Xi oOBVBc9Dq2RwKV7RnWIcV3+ZxrERJp80a4TKMSpQyECkDGiwZLyS/nGfM2+fJKg8 c66ofk+TfsnYZfKaonXwVf+HVqoMLsAo6bxle/0gLT6S3G6DvSGj3pWGqF8uZQJt vpUbqSJBEI0JZTLngkWZRHPrLcCu+W+9/QrkTRYdwZUh5DfS9wbzXVz2Jm3cXpnB os3v+lfJwXS6FBT51zCbO8BKbXPlaIQbLwPRW2+5zI2MaoEocAm0lSU1SXGcOuJY 6N5t6hHHNn7g7Gv8oimHQCKvzOUjnyVCDAn7P7/ILjoV47oQH9QRoNmHNNLjSzj1 4xr4yCg= =PlQh -----END PGP SIGNATURE----- Merge tag 'sound-6.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound 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 ...
This commit is contained in:
		
						commit
						0f1dd5e91e
					
				
					 34 changed files with 447 additions and 230 deletions
				
			
		|  | @ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# | |||
| title: Google SC7280-Herobrine ASoC sound card driver | ||||
| 
 | ||||
| maintainers: | ||||
|   - Srinivasa Rao Mandadapu <srivasam@codeaurora.org> | ||||
|   - Judy Hsiao <judyhsiao@chromium.org> | ||||
| 
 | ||||
| description: | ||||
|  |  | |||
|  | @ -142,6 +142,7 @@ struct tasdevice_priv { | |||
| 
 | ||||
| void tas2781_reset(struct tasdevice_priv *tas_dev); | ||||
| int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, | ||||
| 	struct module *module, | ||||
| 	void (*cont)(const struct firmware *fw, void *context)); | ||||
| struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c); | ||||
| int tasdevice_init(struct tasdevice_priv *tas_priv); | ||||
|  |  | |||
|  | @ -156,7 +156,7 @@ config SND_HDA_SCODEC_CS35L56_I2C | |||
| 	depends on I2C | ||||
| 	depends on ACPI || COMPILE_TEST | ||||
| 	depends on SND_SOC | ||||
| 	select CS_DSP | ||||
| 	select FW_CS_DSP | ||||
| 	select SND_HDA_GENERIC | ||||
| 	select SND_SOC_CS35L56_SHARED | ||||
| 	select SND_HDA_SCODEC_CS35L56 | ||||
|  | @ -171,7 +171,7 @@ config SND_HDA_SCODEC_CS35L56_SPI | |||
| 	depends on SPI_MASTER | ||||
| 	depends on ACPI || COMPILE_TEST | ||||
| 	depends on SND_SOC | ||||
| 	select CS_DSP | ||||
| 	select FW_CS_DSP | ||||
| 	select SND_HDA_GENERIC | ||||
| 	select SND_SOC_CS35L56_SHARED | ||||
| 	select SND_HDA_SCODEC_CS35L56 | ||||
|  |  | |||
|  | @ -91,10 +91,12 @@ static const struct cs35l41_config cs35l41_config_table[] = { | |||
| 	{ "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, | ||||
| 	{ "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, | ||||
| 	{ "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, | ||||
| 	{ "10431E12", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, | ||||
| 	{ "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, | ||||
| 	{ "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, | ||||
| 	{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 }, | ||||
| 	{ "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, | ||||
| 	{ "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, | ||||
| 	{ "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, | ||||
| 	{ "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, | ||||
| 	{ "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[] = { | |||
| 	{ "CSC3551", "10431D1F", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431DA2", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431E02", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431E12", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431EE2", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431F12", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431F1F", generic_dsd_config }, | ||||
| 	{ "CSC3551", "10431F62", generic_dsd_config }, | ||||
| 	{ "CSC3551", "17AA386F", generic_dsd_config }, | ||||
| 	{ "CSC3551", "17AA38B4", generic_dsd_config }, | ||||
| 	{ "CSC3551", "17AA38B5", generic_dsd_config }, | ||||
| 	{ "CSC3551", "17AA38B6", generic_dsd_config }, | ||||
|  |  | |||
|  | @ -344,6 +344,7 @@ enum { | |||
| 	CXT_FIXUP_HP_ZBOOK_MUTE_LED, | ||||
| 	CXT_FIXUP_HEADSET_MIC, | ||||
| 	CXT_FIXUP_HP_MIC_NO_PRESENCE, | ||||
| 	CXT_PINCFG_SWS_JS201D, | ||||
| }; | ||||
| 
 | ||||
| /* for hda_fixup_thinkpad_acpi() */ | ||||
|  | @ -841,6 +842,17 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = { | |||
| 	{} | ||||
| }; | ||||
| 
 | ||||
| /* SuoWoSi/South-holding JS201D with sn6140 */ | ||||
| static const struct hda_pintbl cxt_pincfg_sws_js201d[] = { | ||||
| 	{ 0x16, 0x03211040 }, /* hp out */ | ||||
| 	{ 0x17, 0x91170110 }, /* SPK/Class_D */ | ||||
| 	{ 0x18, 0x95a70130 }, /* Internal mic */ | ||||
| 	{ 0x19, 0x03a11020 }, /* Headset Mic */ | ||||
| 	{ 0x1a, 0x40f001f0 }, /* Not used */ | ||||
| 	{ 0x21, 0x40f001f0 }, /* Not used */ | ||||
| 	{} | ||||
| }; | ||||
| 
 | ||||
| static const struct hda_fixup cxt_fixups[] = { | ||||
| 	[CXT_PINCFG_LENOVO_X200] = { | ||||
| 		.type = HDA_FIXUP_PINS, | ||||
|  | @ -996,6 +1008,10 @@ static const struct hda_fixup cxt_fixups[] = { | |||
| 		.chained = true, | ||||
| 		.chain_id = CXT_FIXUP_HEADSET_MIC, | ||||
| 	}, | ||||
| 	[CXT_PINCFG_SWS_JS201D] = { | ||||
| 		.type = HDA_FIXUP_PINS, | ||||
| 		.v.pins = cxt_pincfg_sws_js201d, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static const struct snd_pci_quirk cxt5045_fixups[] = { | ||||
|  | @ -1069,6 +1085,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
| 	SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), | ||||
| 	SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D), | ||||
| 	SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), | ||||
|  | @ -1109,6 +1126,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { | |||
| 	{ .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" }, | ||||
| 	{ .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" }, | ||||
| 	{ .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" }, | ||||
| 	{ .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" }, | ||||
| 	{} | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -9737,7 +9737,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 	SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c0b, "Dell Oasis 14 RPL-P", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c0e, "Dell Oasis 16", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), | ||||
| 	SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), | ||||
| 	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[] = { | |||
| 	SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	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[] = { | |||
| 	SND_PCI_QUIRK(0x103c, 0x8b45, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b46, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b59, "HP Elite mt645 G7 Mobile Thin Client U89", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | ||||
| 	SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | ||||
| 	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[] = { | |||
| 	SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x16d3, "ASUS UX5304VA", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | ||||
|  | @ -10046,14 +10051,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 	SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), | ||||
| 	SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), | ||||
| 	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[] = { | |||
| 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), | ||||
| 	SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C), | ||||
| 	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, | |||
| 
 | ||||
| 	strscpy(comps->name, dev_name(dev), sizeof(comps->name)); | ||||
| 
 | ||||
| 	ret = tascodec_init(tas_hda->priv, codec, tasdev_fw_ready); | ||||
| 	ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready); | ||||
| 	if (!ret) | ||||
| 		comps->playback_hook = tas2781_hda_playback_hook; | ||||
| 
 | ||||
|  |  | |||
|  | @ -234,6 +234,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { | |||
| 			DMI_MATCH(DMI_PRODUCT_NAME, "82UG"), | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		.driver_data = &acp6x_card, | ||||
| 		.matches = { | ||||
| 			DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | ||||
| 			DMI_MATCH(DMI_PRODUCT_NAME, "82UU"), | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		.driver_data = &acp6x_card, | ||||
| 		.matches = { | ||||
|  | @ -248,6 +255,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { | |||
| 			DMI_MATCH(DMI_PRODUCT_NAME, "82YM"), | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		.driver_data = &acp6x_card, | ||||
| 		.matches = { | ||||
| 			DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | ||||
| 			DMI_MATCH(DMI_PRODUCT_NAME, "83AS"), | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		.driver_data = &acp6x_card, | ||||
| 		.matches = { | ||||
|  |  | |||
|  | @ -51,7 +51,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { | |||
| 	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 }, | ||||
| 	{ CS35L56_SWIRE_DP3_CH3_INPUT,		0x00000029 }, | ||||
| 	{ CS35L56_SWIRE_DP3_CH4_INPUT,		0x00000028 }, | ||||
| 	{ CS35L56_IRQ1_CFG,			0x00000000 }, | ||||
| 	{ CS35L56_IRQ1_MASK_1,			0x83ffffff }, | ||||
| 	{ CS35L56_IRQ1_MASK_2,			0xffff7fff }, | ||||
| 	{ CS35L56_IRQ1_MASK_4,			0xe0ffffff }, | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| // Copyright (C) 2023 Cirrus Logic, Inc. and
 | ||||
| //                    Cirrus Logic International Semiconductor Ltd.
 | ||||
| 
 | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/completion.h> | ||||
| #include <linux/debugfs.h> | ||||
| #include <linux/delay.h> | ||||
|  | @ -15,6 +16,7 @@ | |||
| #include <linux/module.h> | ||||
| #include <linux/pm.h> | ||||
| #include <linux/pm_runtime.h> | ||||
| #include <linux/property.h> | ||||
| #include <linux/regmap.h> | ||||
| #include <linux/regulator/consumer.h> | ||||
| #include <linux/slab.h> | ||||
|  | @ -68,6 +70,66 @@ static const char * const cs35l56_asp1_mux_control_names[] = { | |||
| 	"ASP1 TX1 Source", "ASP1 TX2 Source", "ASP1 TX3 Source", "ASP1 TX4 Source" | ||||
| }; | ||||
| 
 | ||||
| static int cs35l56_sync_asp1_mixer_widgets_with_firmware(struct cs35l56_private *cs35l56) | ||||
| { | ||||
| 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component); | ||||
| 	const char *prefix = cs35l56->component->name_prefix; | ||||
| 	char full_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||||
| 	const char *name; | ||||
| 	struct snd_kcontrol *kcontrol; | ||||
| 	struct soc_enum *e; | ||||
| 	unsigned int val[4]; | ||||
| 	int i, item, ret; | ||||
| 
 | ||||
| 	if (cs35l56->asp1_mixer_widgets_initialized) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Resume so we can read the registers from silicon if the regmap | ||||
| 	 * cache has not yet been populated. | ||||
| 	 */ | ||||
| 	ret = pm_runtime_resume_and_get(cs35l56->base.dev); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	/* Wait for firmware download and reboot */ | ||||
| 	cs35l56_wait_dsp_ready(cs35l56); | ||||
| 
 | ||||
| 	ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, | ||||
| 			       val, ARRAY_SIZE(val)); | ||||
| 
 | ||||
| 	pm_runtime_mark_last_busy(cs35l56->base.dev); | ||||
| 	pm_runtime_put_autosuspend(cs35l56->base.dev); | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) { | ||||
| 		name = cs35l56_asp1_mux_control_names[i]; | ||||
| 
 | ||||
| 		if (prefix) { | ||||
| 			snprintf(full_name, sizeof(full_name), "%s %s", prefix, name); | ||||
| 			name = full_name; | ||||
| 		} | ||||
| 
 | ||||
| 		kcontrol = snd_soc_card_get_kcontrol(dapm->card, name); | ||||
| 		if (!kcontrol) { | ||||
| 			dev_warn(cs35l56->base.dev, "Could not find control %s\n", name); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		e = (struct soc_enum *)kcontrol->private_value; | ||||
| 		item = snd_soc_enum_val_to_item(e, val[i] & CS35L56_ASP_TXn_SRC_MASK); | ||||
| 		snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	cs35l56->asp1_mixer_widgets_initialized = true; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, | ||||
| 				      struct snd_ctl_elem_value *ucontrol) | ||||
| { | ||||
|  | @ -78,9 +140,9 @@ static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, | |||
| 	unsigned int addr, val; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* Wait for mux to be initialized */ | ||||
| 	cs35l56_wait_dsp_ready(cs35l56); | ||||
| 	flush_work(&cs35l56->mux_init_work); | ||||
| 	ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	addr = cs35l56_asp1_mixer_regs[index]; | ||||
| 	ret = regmap_read(cs35l56->base.regmap, addr, &val); | ||||
|  | @ -106,16 +168,16 @@ static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, | |||
| 	bool changed; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* Wait for mux to be initialized */ | ||||
| 	cs35l56_wait_dsp_ready(cs35l56); | ||||
| 	flush_work(&cs35l56->mux_init_work); | ||||
| 	ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	addr = cs35l56_asp1_mixer_regs[index]; | ||||
| 	val = snd_soc_enum_item_to_val(e, item); | ||||
| 
 | ||||
| 	ret = regmap_update_bits_check(cs35l56->base.regmap, addr, | ||||
| 				       CS35L56_ASP_TXn_SRC_MASK, val, &changed); | ||||
| 	if (!ret) | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	if (changed) | ||||
|  | @ -124,70 +186,6 @@ static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, | |||
| 	return changed; | ||||
| } | ||||
| 
 | ||||
| static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l56) | ||||
| { | ||||
| 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component); | ||||
| 	const char *prefix = cs35l56->component->name_prefix; | ||||
| 	char full_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||||
| 	const char *name; | ||||
| 	struct snd_kcontrol *kcontrol; | ||||
| 	struct soc_enum *e; | ||||
| 	unsigned int val[4]; | ||||
| 	int i, item, ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Resume so we can read the registers from silicon if the regmap | ||||
| 	 * cache has not yet been populated. | ||||
| 	 */ | ||||
| 	ret = pm_runtime_resume_and_get(cs35l56->base.dev); | ||||
| 	if (ret < 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, | ||||
| 			       val, ARRAY_SIZE(val)); | ||||
| 
 | ||||
| 	pm_runtime_mark_last_busy(cs35l56->base.dev); | ||||
| 	pm_runtime_put_autosuspend(cs35l56->base.dev); | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	snd_soc_card_mutex_lock(dapm->card); | ||||
| 	WARN_ON(!dapm->card->instantiated); | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) { | ||||
| 		name = cs35l56_asp1_mux_control_names[i]; | ||||
| 
 | ||||
| 		if (prefix) { | ||||
| 			snprintf(full_name, sizeof(full_name), "%s %s", prefix, name); | ||||
| 			name = full_name; | ||||
| 		} | ||||
| 
 | ||||
| 		kcontrol = snd_soc_card_get_kcontrol(dapm->card, name); | ||||
| 		if (!kcontrol) { | ||||
| 			dev_warn(cs35l56->base.dev, "Could not find control %s\n", name); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		e = (struct soc_enum *)kcontrol->private_value; | ||||
| 		item = snd_soc_enum_val_to_item(e, val[i] & CS35L56_ASP_TXn_SRC_MASK); | ||||
| 		snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	snd_soc_card_mutex_unlock(dapm->card); | ||||
| } | ||||
| 
 | ||||
| static void cs35l56_mux_init_work(struct work_struct *work) | ||||
| { | ||||
| 	struct cs35l56_private *cs35l56 = container_of(work, | ||||
| 						       struct cs35l56_private, | ||||
| 						       mux_init_work); | ||||
| 
 | ||||
| 	cs35l56_mark_asp1_mixer_widgets_dirty(cs35l56); | ||||
| } | ||||
| 
 | ||||
| static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); | ||||
| 
 | ||||
| static const struct snd_kcontrol_new cs35l56_controls[] = { | ||||
|  | @ -936,14 +934,6 @@ static void cs35l56_dsp_work(struct work_struct *work) | |||
| 	else | ||||
| 		cs35l56_patch(cs35l56, firmware_missing); | ||||
| 
 | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Set starting value of ASP1 mux widgets. Updating a mux takes | ||||
| 	 * the DAPM mutex. Post this to a separate job so that DAPM | ||||
| 	 * power-up can wait for dsp_work to complete without deadlocking | ||||
| 	 * on the DAPM mutex. | ||||
| 	 */ | ||||
| 	queue_work(cs35l56->dsp_wq, &cs35l56->mux_init_work); | ||||
| err: | ||||
| 	pm_runtime_mark_last_busy(cs35l56->base.dev); | ||||
| 	pm_runtime_put_autosuspend(cs35l56->base.dev); | ||||
|  | @ -989,6 +979,13 @@ static int cs35l56_component_probe(struct snd_soc_component *component) | |||
| 	debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate); | ||||
| 	debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The widgets for the ASP1TX mixer can't be initialized | ||||
| 	 * until the firmware has been downloaded and rebooted. | ||||
| 	 */ | ||||
| 	regcache_drop_region(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX4_INPUT); | ||||
| 	cs35l56->asp1_mixer_widgets_initialized = false; | ||||
| 
 | ||||
| 	queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); | ||||
| 
 | ||||
| 	return 0; | ||||
|  | @ -999,7 +996,6 @@ static void cs35l56_component_remove(struct snd_soc_component *component) | |||
| 	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | ||||
| 
 | ||||
| 	cancel_work_sync(&cs35l56->dsp_work); | ||||
| 	cancel_work_sync(&cs35l56->mux_init_work); | ||||
| 
 | ||||
| 	if (cs35l56->dsp.cs_dsp.booted) | ||||
| 		wm_adsp_power_down(&cs35l56->dsp); | ||||
|  | @ -1070,10 +1066,8 @@ int cs35l56_system_suspend(struct device *dev) | |||
| 
 | ||||
| 	dev_dbg(dev, "system_suspend\n"); | ||||
| 
 | ||||
| 	if (cs35l56->component) { | ||||
| 	if (cs35l56->component) | ||||
| 		flush_work(&cs35l56->dsp_work); | ||||
| 		cancel_work_sync(&cs35l56->mux_init_work); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The interrupt line is normally shared, but after we start suspending | ||||
|  | @ -1224,7 +1218,6 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) | |||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); | ||||
| 	INIT_WORK(&cs35l56->mux_init_work, cs35l56_mux_init_work); | ||||
| 
 | ||||
| 	dsp = &cs35l56->dsp; | ||||
| 	cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp); | ||||
|  | @ -1269,6 +1262,94 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Some SoundWire laptops have a spk-id-gpios property but it points to | ||||
|  * the wrong ACPI Device node so can't be used to get the GPIO. Try to | ||||
|  * find the SDCA node containing the GpioIo resource and add a GPIO | ||||
|  * mapping to it. | ||||
|  */ | ||||
| static const struct acpi_gpio_params cs35l56_af01_first_gpio = { 0, 0, false }; | ||||
| static const struct acpi_gpio_mapping cs35l56_af01_spkid_gpios_mapping[] = { | ||||
| 	{ "spk-id-gpios", &cs35l56_af01_first_gpio, 1 }, | ||||
| 	{ } | ||||
| }; | ||||
| 
 | ||||
| static void cs35l56_acpi_dev_release_driver_gpios(void *adev) | ||||
| { | ||||
| 	acpi_dev_remove_driver_gpios(adev); | ||||
| } | ||||
| 
 | ||||
| static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l56) | ||||
| { | ||||
| 	struct fwnode_handle *af01_fwnode; | ||||
| 	const union acpi_object *obj; | ||||
| 	struct gpio_desc *desc; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* Find the SDCA node containing the GpioIo */ | ||||
| 	af01_fwnode = device_get_named_child_node(cs35l56->base.dev, "AF01"); | ||||
| 	if (!af01_fwnode) { | ||||
| 		dev_dbg(cs35l56->base.dev, "No AF01 node\n"); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = acpi_dev_get_property(ACPI_COMPANION(cs35l56->base.dev), | ||||
| 				    "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj); | ||||
| 	if (ret) { | ||||
| 		dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 
 | ||||
| 	/* The broken properties we can handle are a 4-element package (one GPIO) */ | ||||
| 	if (obj->package.count != 4) { | ||||
| 		dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n", | ||||
| 			 obj->package.count); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Add a GPIO mapping if it doesn't already have one */ | ||||
| 	if (!fwnode_property_present(af01_fwnode, "spk-id-gpios")) { | ||||
| 		struct acpi_device *adev = to_acpi_device_node(af01_fwnode); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Can't use devm_acpi_dev_add_driver_gpios() because the | ||||
| 		 * mapping isn't being added to the node pointed to by | ||||
| 		 * ACPI_COMPANION(). | ||||
| 		 */ | ||||
| 		ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping); | ||||
| 		if (ret) { | ||||
| 			return dev_err_probe(cs35l56->base.dev, ret, | ||||
| 					     "Failed to add gpio mapping to AF01\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		ret = devm_add_action_or_reset(cs35l56->base.dev, | ||||
| 					       cs35l56_acpi_dev_release_driver_gpios, | ||||
| 					       adev); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 
 | ||||
| 		dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL); | ||||
| 	if (IS_ERR(desc)) { | ||||
| 		ret = PTR_ERR(desc); | ||||
| 		return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	ret = gpiod_get_value_cansleep(desc); | ||||
| 	gpiod_put(desc); | ||||
| 
 | ||||
| 	if (ret < 0) { | ||||
| 		dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n"); | ||||
| 		return ret; | ||||
| 		} | ||||
| 
 | ||||
| 	dev_info(cs35l56->base.dev, "Got spk-id from AF01\n"); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int cs35l56_common_probe(struct cs35l56_private *cs35l56) | ||||
| { | ||||
| 	int ret; | ||||
|  | @ -1313,6 +1394,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) | |||
| 	} | ||||
| 
 | ||||
| 	ret = cs35l56_get_speaker_id(&cs35l56->base); | ||||
| 	if (ACPI_COMPANION(cs35l56->base.dev) && cs35l56->sdw_peripheral && (ret == -ENOENT)) | ||||
| 		ret = cs35l56_try_get_broken_sdca_spkid_gpio(cs35l56); | ||||
| 
 | ||||
| 	if ((ret < 0) && (ret != -ENOENT)) | ||||
| 		goto err; | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,7 +34,6 @@ struct cs35l56_private { | |||
| 	struct wm_adsp dsp; /* must be first member */ | ||||
| 	struct cs35l56_base base; | ||||
| 	struct work_struct dsp_work; | ||||
| 	struct work_struct mux_init_work; | ||||
| 	struct workqueue_struct *dsp_wq; | ||||
| 	struct snd_soc_component *component; | ||||
| 	struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; | ||||
|  | @ -52,6 +51,7 @@ struct cs35l56_private { | |||
| 	u8 asp_slot_count; | ||||
| 	bool tdm_mode; | ||||
| 	bool sysclk_set; | ||||
| 	bool asp1_mixer_widgets_initialized; | ||||
| 	u8 old_sdw_clock_scale; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2257,7 +2257,10 @@ static int cs42l43_codec_probe(struct platform_device *pdev) | |||
| 	pm_runtime_use_autosuspend(priv->dev); | ||||
| 	pm_runtime_set_active(priv->dev); | ||||
| 	pm_runtime_get_noresume(priv->dev); | ||||
| 	devm_pm_runtime_enable(priv->dev); | ||||
| 
 | ||||
| 	ret = devm_pm_runtime_enable(priv->dev); | ||||
| 	if (ret) | ||||
| 		goto err_pm; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { | ||||
| 		ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name, | ||||
|  | @ -2333,8 +2336,47 @@ static int cs42l43_codec_runtime_resume(struct device *dev) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static DEFINE_RUNTIME_DEV_PM_OPS(cs42l43_codec_pm_ops, NULL, | ||||
| 				 cs42l43_codec_runtime_resume, NULL); | ||||
| static int cs42l43_codec_suspend(struct device *dev) | ||||
| { | ||||
| 	struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	disable_irq(cs42l43->irq); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int cs42l43_codec_suspend_noirq(struct device *dev) | ||||
| { | ||||
| 	struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	enable_irq(cs42l43->irq); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int cs42l43_codec_resume(struct device *dev) | ||||
| { | ||||
| 	struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	enable_irq(cs42l43->irq); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int cs42l43_codec_resume_noirq(struct device *dev) | ||||
| { | ||||
| 	struct cs42l43 *cs42l43 = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	disable_irq(cs42l43->irq); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct dev_pm_ops cs42l43_codec_pm_ops = { | ||||
| 	SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) | ||||
| 	NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq) | ||||
| 	RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) | ||||
| }; | ||||
| 
 | ||||
| static const struct platform_device_id cs42l43_codec_id_table[] = { | ||||
| 	{ "cs42l43-codec", }, | ||||
|  |  | |||
|  | @ -3317,6 +3317,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
| 				    report, SND_JACK_HEADPHONE); | ||||
| 		snd_soc_jack_report(rt5645->mic_jack, | ||||
| 				    report, SND_JACK_MICROPHONE); | ||||
| 		mutex_unlock(&rt5645->jd_mutex); | ||||
| 		return; | ||||
| 	case 4: | ||||
| 		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 = { | |||
| 	.mono_speaker = true, | ||||
| }; | ||||
| 
 | ||||
| static const struct rt5645_platform_data jd_mode3_inv_data = { | ||||
| 	.jd_mode = 3, | ||||
| 	.inv_jd1_1 = true, | ||||
| }; | ||||
| 
 | ||||
| static const struct rt5645_platform_data jd_mode3_platform_data = { | ||||
| 	.jd_mode = 3, | ||||
| }; | ||||
|  | @ -3837,6 +3843,16 @@ static const struct dmi_system_id dmi_platform_data[] = { | |||
| 		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | ||||
| 		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), | ||||
| 		  DMI_EXACT_MATCH(DMI_BOARD_VERSION, "Default string"), | ||||
| 		  /*
 | ||||
| 		   * Above strings are too generic, LattePanda BIOS versions for | ||||
| 		   * all 4 hw revisions are: | ||||
| 		   * DF-BI-7-S70CR100-* | ||||
| 		   * DF-BI-7-S70CR110-* | ||||
| 		   * DF-BI-7-S70CR200-* | ||||
| 		   * LP-BS-7-S70CR700-* | ||||
| 		   * Do a partial match for S70CR to avoid false positive matches. | ||||
| 		   */ | ||||
| 		  DMI_MATCH(DMI_BIOS_VERSION, "S70CR"), | ||||
| 		}, | ||||
| 		.driver_data = (void *)&lattepanda_board_platform_data, | ||||
| 	}, | ||||
|  | @ -3871,6 +3887,16 @@ static const struct dmi_system_id dmi_platform_data[] = { | |||
| 		}, | ||||
| 		.driver_data = (void *)&intel_braswell_platform_data, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.ident = "Meegopad T08", | ||||
| 		.matches = { | ||||
| 			DMI_MATCH(DMI_SYS_VENDOR, "Default string"), | ||||
| 			DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), | ||||
| 			DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), | ||||
| 			DMI_MATCH(DMI_BOARD_VERSION, "V1.1"), | ||||
| 		}, | ||||
| 		.driver_data = (void *)&jd_mode3_inv_data, | ||||
| 	}, | ||||
| 	{ } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -267,6 +267,7 @@ void tas2781_reset(struct tasdevice_priv *tas_dev) | |||
| EXPORT_SYMBOL_GPL(tas2781_reset); | ||||
| 
 | ||||
| int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, | ||||
| 	struct module *module, | ||||
| 	void (*cont)(const struct firmware *fw, void *context)) | ||||
| { | ||||
| 	int ret = 0; | ||||
|  | @ -280,7 +281,7 @@ int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, | |||
| 		tas_priv->dev_name, tas_priv->ndev); | ||||
| 	crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL); | ||||
| 	tas_priv->codec = codec; | ||||
| 	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, | ||||
| 	ret = request_firmware_nowait(module, FW_ACTION_UEVENT, | ||||
| 		tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv, | ||||
| 		cont); | ||||
| 	if (ret) | ||||
|  |  | |||
|  | @ -566,7 +566,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) | |||
| { | ||||
| 	struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); | ||||
| 
 | ||||
| 	return tascodec_init(tas_priv, codec, tasdevice_fw_ready); | ||||
| 	return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready); | ||||
| } | ||||
| 
 | ||||
| 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) | |||
| 	return 0; | ||||
| 
 | ||||
| err_i915_init: | ||||
| 	pci_free_irq(pci, 0, adev); | ||||
| 	pci_free_irq(pci, 0, bus); | ||||
| 	pci_free_irq_vectors(pci); | ||||
| 	pci_clear_master(pci); | ||||
| 	pci_set_drvdata(pci, NULL); | ||||
| err_acquire_irq: | ||||
|  |  | |||
|  | @ -857,7 +857,7 @@ assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcf | |||
| 	} | ||||
| 
 | ||||
| 	/* If topology sets value don't overwrite it */ | ||||
| 	if (cfg->copier.vindex.i2s.instance) | ||||
| 	if (cfg->copier.vindex.val) | ||||
| 		return; | ||||
| 
 | ||||
| 	mach = dev_get_platdata(comp->card->dev); | ||||
|  |  | |||
|  | @ -241,7 +241,8 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* fix index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) { | ||||
| 		if (!strcmp(byt_cht_cx2072x_dais[i].codecs->name, | ||||
| 		if (byt_cht_cx2072x_dais[i].codecs->name && | ||||
| 		    !strcmp(byt_cht_cx2072x_dais[i].codecs->name, | ||||
| 			    "i2c-14F10720:00")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -245,7 +245,8 @@ static int bytcht_da7213_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* fix index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(dailink); i++) { | ||||
| 		if (!strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) { | ||||
| 		if (dailink[i].codecs->name && | ||||
| 		    !strcmp(dailink[i].codecs->name, "i2c-DLGS7213:00")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
| 		} | ||||
|  |  | |||
|  | @ -546,7 +546,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* fix index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) { | ||||
| 		if (!strcmp(byt_cht_es8316_dais[i].codecs->name, | ||||
| 		if (byt_cht_es8316_dais[i].codecs->name && | ||||
| 		    !strcmp(byt_cht_es8316_dais[i].codecs->name, | ||||
| 			    "i2c-ESSX8316:00")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -1652,7 +1652,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* fix index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { | ||||
| 		if (!strcmp(byt_rt5640_dais[i].codecs->name, | ||||
| 		if (byt_rt5640_dais[i].codecs->name && | ||||
| 		    !strcmp(byt_rt5640_dais[i].codecs->name, | ||||
| 			    "i2c-10EC5640:00")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -910,7 +910,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* fix index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { | ||||
| 		if (!strcmp(byt_rt5651_dais[i].codecs->name, | ||||
| 		if (byt_rt5651_dais[i].codecs->name && | ||||
| 		    !strcmp(byt_rt5651_dais[i].codecs->name, | ||||
| 			    "i2c-10EC5651:00")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -605,7 +605,8 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* find index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) { | ||||
| 		if (!strcmp(byt_wm5102_dais[i].codecs->name, | ||||
| 		if (byt_wm5102_dais[i].codecs->name && | ||||
| 		    !strcmp(byt_wm5102_dais[i].codecs->name, | ||||
| 			    "wm5102-codec")) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -40,7 +40,6 @@ struct cht_acpi_card { | |||
| struct cht_mc_private { | ||||
| 	struct snd_soc_jack jack; | ||||
| 	struct cht_acpi_card *acpi_card; | ||||
| 	char codec_name[SND_ACPI_I2C_ID_LEN]; | ||||
| 	struct clk *mclk; | ||||
| }; | ||||
| 
 | ||||
|  | @ -567,14 +566,14 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
| 	} | ||||
| 
 | ||||
| 	card->dev = &pdev->dev; | ||||
| 	sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id); | ||||
| 
 | ||||
| 	/* set correct codec name */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) | ||||
| 		if (!strcmp(card->dai_link[i].codecs->name, | ||||
| 		if (cht_dailink[i].codecs->name && | ||||
| 		    !strcmp(cht_dailink[i].codecs->name, | ||||
| 			    "i2c-10EC5645:00")) { | ||||
| 			card->dai_link[i].codecs->name = drv->codec_name; | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 	/* fixup codec name based on HID */ | ||||
|  |  | |||
|  | @ -466,7 +466,8 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* find index of codec dai */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { | ||||
| 		if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) { | ||||
| 		if (cht_dailink[i].codecs->name && | ||||
| 		    !strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) { | ||||
| 			dai_index = i; | ||||
| 			break; | ||||
| 		} | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ static struct snd_pcm_hardware q6apm_dai_hardware_playback = { | |||
| 	.fifo_size =            0, | ||||
| }; | ||||
| 
 | ||||
| static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv) | ||||
| static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *priv) | ||||
| { | ||||
| 	struct q6apm_dai_rtd *prtd = priv; | ||||
| 	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 | |||
| } | ||||
| 
 | ||||
| static void event_handler_compr(uint32_t opcode, uint32_t token, | ||||
| 				uint32_t *payload, void *priv) | ||||
| 				void *payload, void *priv) | ||||
| { | ||||
| 	struct q6apm_dai_rtd *prtd = priv; | ||||
| 	struct snd_compr_stream *substream = prtd->cstream; | ||||
|  | @ -352,7 +352,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, | |||
| 
 | ||||
| 	spin_lock_init(&prtd->lock); | ||||
| 	prtd->substream = substream; | ||||
| 	prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler, prtd, graph_id); | ||||
| 	prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id); | ||||
| 	if (IS_ERR(prtd->graph)) { | ||||
| 		dev_err(dev, "%s: Could not allocate memory\n", __func__); | ||||
| 		ret = PTR_ERR(prtd->graph); | ||||
|  | @ -496,7 +496,7 @@ static int q6apm_dai_compr_open(struct snd_soc_component *component, | |||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	prtd->cstream = stream; | ||||
| 	prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler_compr, prtd, graph_id); | ||||
| 	prtd->graph = q6apm_graph_open(dev, event_handler_compr, prtd, graph_id); | ||||
| 	if (IS_ERR(prtd->graph)) { | ||||
| 		ret = PTR_ERR(prtd->graph); | ||||
| 		kfree(prtd); | ||||
|  |  | |||
|  | @ -188,11 +188,13 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context) | |||
| 
 | ||||
| 	dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write); | ||||
| 	if (dsp_ack) { | ||||
| 		spin_lock_irq(&sdev->ipc_lock); | ||||
| 		/* handle immediate reply from DSP core */ | ||||
| 		acp_dsp_ipc_get_reply(sdev); | ||||
| 		snd_sof_ipc_reply(sdev, 0); | ||||
| 		/* set the done bit */ | ||||
| 		acp_dsp_ipc_dsp_done(sdev); | ||||
| 		spin_unlock_irq(&sdev->ipc_lock); | ||||
| 		ipc_irq = true; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -355,21 +355,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context) | |||
| 	unsigned int count = ACP_HW_SEM_RETRY_COUNT; | ||||
| 
 | ||||
| 	spin_lock_irq(&sdev->ipc_lock); | ||||
| 	while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { | ||||
| 		/* Wait until acquired HW Semaphore lock or timeout */ | ||||
| 		count--; | ||||
| 		if (!count) { | ||||
| 			dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); | ||||
| 			spin_unlock_irq(&sdev->ipc_lock); | ||||
| 			return IRQ_NONE; | ||||
| 		} | ||||
| 	/* Wait until acquired HW Semaphore lock or timeout */ | ||||
| 	while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset) && --count) | ||||
| 		; | ||||
| 	spin_unlock_irq(&sdev->ipc_lock); | ||||
| 
 | ||||
| 	if (!count) { | ||||
| 		dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); | ||||
| 		return IRQ_NONE; | ||||
| 	} | ||||
| 
 | ||||
| 	sof_ops(sdev)->irq_thread(irq, sdev); | ||||
| 	/* Unlock or Release HW Semaphore */ | ||||
| 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0); | ||||
| 
 | ||||
| 	spin_unlock_irq(&sdev->ipc_lock); | ||||
| 	return IRQ_HANDLED; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ static const struct sof_dev_desc lnl_desc = { | |||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ace-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_4] = "sof-lnl.ri", | ||||
|  |  | |||
|  | @ -33,18 +33,18 @@ static const struct sof_dev_desc tgl_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/tgl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/tgl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-tgl.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-tgl.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-tgl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -66,18 +66,18 @@ static const struct sof_dev_desc tglh_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/tgl-h", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/tgl-h", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/tgl-h", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/tgl-h", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-tgl-h.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-tgl-h.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-tgl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -98,18 +98,18 @@ static const struct sof_dev_desc ehl_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/ehl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/ehl", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/ehl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/ehl", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-ehl.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-ehl.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-ehl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -131,18 +131,18 @@ static const struct sof_dev_desc adls_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/adl-s", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-s", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/adl-s", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-s", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-adl-s.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-adl-s.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-adl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -164,18 +164,18 @@ static const struct sof_dev_desc adl_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/adl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/adl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-adl.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-adl.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-adl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -197,18 +197,18 @@ static const struct sof_dev_desc adl_n_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/adl-n", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/adl-n", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/adl-n", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/adl-n", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-adl-n.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-adl-n.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-adl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -230,18 +230,18 @@ static const struct sof_dev_desc rpls_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/rpl-s", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl-s", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/rpl-s", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl-s", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-rpl-s.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-rpl-s.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-rpl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  | @ -263,18 +263,18 @@ static const struct sof_dev_desc rpl_desc = { | |||
| 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */ | ||||
| 	.default_fw_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs/rpl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4/rpl", | ||||
| 	}, | ||||
| 	.default_lib_path = { | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-lib/rpl", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/rpl", | ||||
| 	}, | ||||
| 	.default_tplg_path = { | ||||
| 		[SOF_IPC_TYPE_3] = "intel/sof-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/avs-tplg", | ||||
| 		[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", | ||||
| 	}, | ||||
| 	.default_fw_filename = { | ||||
| 		[SOF_IPC_TYPE_3] = "sof-rpl.ri", | ||||
| 		[SOF_IPC_TYPE_4] = "dsp_basefw.bin", | ||||
| 		[SOF_IPC_TYPE_4] = "sof-rpl.ri", | ||||
| 	}, | ||||
| 	.nocodec_tplg_filename = "sof-rpl-nocodec.tplg", | ||||
| 	.ops = &sof_tgl_ops, | ||||
|  |  | |||
|  | @ -2360,6 +2360,44 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler, | ||||
| 					 bool *dyn_widgets, bool verify) | ||||
| { | ||||
| 	struct sof_ipc_fw_version *v = &sdev->fw_ready.version; | ||||
| 	struct snd_sof_widget *swidget; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	list_for_each_entry(swidget, &sdev->widget_list, list) { | ||||
| 		if (swidget->dynamic_pipeline_widget) { | ||||
| 			*dyn_widgets = true; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Do not free widgets for static pipelines with FW older than SOF2.2 */ | ||||
| 		if (!verify && !swidget->dynamic_pipeline_widget && | ||||
| 		    SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) { | ||||
| 			mutex_lock(&swidget->setup_mutex); | ||||
| 			swidget->use_count = 0; | ||||
| 			mutex_unlock(&swidget->setup_mutex); | ||||
| 			if (swidget->spipe) | ||||
| 				swidget->spipe->complete = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		if (include_scheduler && swidget->id != snd_soc_dapm_scheduler) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler) | ||||
| 			continue; | ||||
| 
 | ||||
| 		ret = sof_widget_free(sdev, swidget); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * For older firmware, this function doesn't free widgets for static pipelines during suspend. | ||||
|  * It only resets use_count for all widgets. | ||||
|  | @ -2376,29 +2414,18 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif | |||
| 	 * This function is called during suspend and for one-time topology verification during | ||||
| 	 * first boot. In both cases, there is no need to protect swidget->use_count and | ||||
| 	 * sroute->setup because during suspend all running streams are suspended and during | ||||
| 	 * topology loading the sound card unavailable to open PCMs. | ||||
| 	 * topology loading the sound card unavailable to open PCMs. Do not free the scheduler | ||||
| 	 * widgets yet so that the secondary cores do not get powered down before all the widgets | ||||
| 	 * associated with the scheduler are freed. | ||||
| 	 */ | ||||
| 	list_for_each_entry(swidget, &sdev->widget_list, list) { | ||||
| 		if (swidget->dynamic_pipeline_widget) { | ||||
| 			dyn_widgets = true; | ||||
| 			continue; | ||||
| 		} | ||||
| 	ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 		/* Do not free widgets for static pipelines with FW older than SOF2.2 */ | ||||
| 		if (!verify && !swidget->dynamic_pipeline_widget && | ||||
| 		    SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) { | ||||
| 			mutex_lock(&swidget->setup_mutex); | ||||
| 			swidget->use_count = 0; | ||||
| 			mutex_unlock(&swidget->setup_mutex); | ||||
| 			if (swidget->spipe) | ||||
| 				swidget->spipe->complete = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		ret = sof_widget_free(sdev, swidget); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 	} | ||||
| 	/* free all the scheduler widgets now */ | ||||
| 	ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Tear down all pipelines associated with PCMs that did not get suspended | ||||
|  |  | |||
|  | @ -1067,7 +1067,7 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (hdr.size < sizeof(hdr)) { | ||||
| 	if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) { | ||||
| 		dev_err(sdev->dev, "The received message size is invalid\n"); | ||||
| 		return; | ||||
| 	} | ||||
|  |  | |||
|  | @ -413,7 +413,18 @@ skip_pause_transition: | |||
| 	ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list); | ||||
| 	if (ret < 0) { | ||||
| 		dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state); | ||||
| 		goto free; | ||||
| 		/*
 | ||||
| 		 * workaround: if the firmware is crashed while setting the | ||||
| 		 * pipelines to reset state we must ignore the error code and | ||||
| 		 * reset it to 0. | ||||
| 		 * Since the firmware is crashed we will not send IPC messages | ||||
| 		 * and we are going to see errors printed, but the state of the | ||||
| 		 * widgets will be correct for the next boot. | ||||
| 		 */ | ||||
| 		if (sdev->fw_state != SOF_FW_CRASHED || state != SOF_IPC4_PIPE_RESET) | ||||
| 			goto free; | ||||
| 
 | ||||
| 		ret = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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, | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor( | ||||
| 					struct usb_host_interface *hostif, uint8_t jack_id) | ||||
| /* return iJack for the corresponding jackID */ | ||||
| static int find_usb_ijack(struct usb_host_interface *hostif, uint8_t jack_id) | ||||
| { | ||||
| 	unsigned char *extra = hostif->extra; | ||||
| 	int extralen = hostif->extralen; | ||||
| 	struct usb_descriptor_header *h; | ||||
| 	struct usb_midi_out_jack_descriptor *outjd; | ||||
| 	struct usb_midi_in_jack_descriptor *injd; | ||||
| 	size_t sz; | ||||
| 
 | ||||
| 	while (extralen > 4) { | ||||
| 		struct usb_midi_in_jack_descriptor *injd = | ||||
| 				(struct usb_midi_in_jack_descriptor *)extra; | ||||
| 		h = (struct usb_descriptor_header *)extra; | ||||
| 		if (h->bDescriptorType != USB_DT_CS_INTERFACE) | ||||
| 			goto next; | ||||
| 
 | ||||
| 		if (injd->bLength >= sizeof(*injd) && | ||||
| 		    injd->bDescriptorType == USB_DT_CS_INTERFACE && | ||||
| 		    injd->bDescriptorSubtype == UAC_MIDI_IN_JACK && | ||||
| 				injd->bJackID == jack_id) | ||||
| 			return injd; | ||||
| 		if (!extra[0]) | ||||
| 			break; | ||||
| 		extralen -= extra[0]; | ||||
| 		extra += extra[0]; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor( | ||||
| 					struct usb_host_interface *hostif, uint8_t jack_id) | ||||
| { | ||||
| 	unsigned char *extra = hostif->extra; | ||||
| 	int extralen = hostif->extralen; | ||||
| 
 | ||||
| 	while (extralen > 4) { | ||||
| 		struct usb_midi_out_jack_descriptor *outjd = | ||||
| 				(struct usb_midi_out_jack_descriptor *)extra; | ||||
| 
 | ||||
| 		if (outjd->bLength >= sizeof(*outjd) && | ||||
| 		    outjd->bDescriptorType == USB_DT_CS_INTERFACE && | ||||
| 		outjd = (struct usb_midi_out_jack_descriptor *)h; | ||||
| 		if (h->bLength >= sizeof(*outjd) && | ||||
| 		    outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK && | ||||
| 				outjd->bJackID == jack_id) | ||||
| 			return outjd; | ||||
| 		    outjd->bJackID == jack_id) { | ||||
| 			sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins); | ||||
| 			if (outjd->bLength < sz) | ||||
| 				goto next; | ||||
| 			return *(extra + sz - 1); | ||||
| 		} | ||||
| 
 | ||||
| 		injd = (struct usb_midi_in_jack_descriptor *)h; | ||||
| 		if (injd->bLength >= sizeof(*injd) && | ||||
| 		    injd->bDescriptorSubtype == UAC_MIDI_IN_JACK && | ||||
| 		    injd->bJackID == jack_id) | ||||
| 			return injd->iJack; | ||||
| 
 | ||||
| next: | ||||
| 		if (!extra[0]) | ||||
| 			break; | ||||
| 		extralen -= extra[0]; | ||||
| 		extra += extra[0]; | ||||
| 	} | ||||
| 	return NULL; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 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, | |||
| 	const char *name_format; | ||||
| 	struct usb_interface *intf; | ||||
| 	struct usb_host_interface *hostif; | ||||
| 	struct usb_midi_in_jack_descriptor *injd; | ||||
| 	struct usb_midi_out_jack_descriptor *outjd; | ||||
| 	uint8_t jack_name_buf[32]; | ||||
| 	uint8_t *default_jack_name = "MIDI"; | ||||
| 	uint8_t *jack_name = default_jack_name; | ||||
| 	uint8_t iJack; | ||||
| 	size_t sz; | ||||
| 	int res; | ||||
| 
 | ||||
| 	struct snd_rawmidi_substream *substream = | ||||
|  | @ -1816,21 +1807,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, | |||
| 	intf = umidi->iface; | ||||
| 	if (intf && jack_id >= 0) { | ||||
| 		hostif = intf->cur_altsetting; | ||||
| 		iJack = 0; | ||||
| 		if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) { | ||||
| 			/* in jacks connect to outs */ | ||||
| 			outjd = find_usb_out_jack_descriptor(hostif, jack_id); | ||||
| 			if (outjd) { | ||||
| 				sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins); | ||||
| 				if (outjd->bLength >= sz) | ||||
| 					iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t)); | ||||
| 			} | ||||
| 		} else { | ||||
| 			/* and out jacks connect to ins */ | ||||
| 			injd = find_usb_in_jack_descriptor(hostif, jack_id); | ||||
| 			if (injd) | ||||
| 				iJack = injd->iJack; | ||||
| 		} | ||||
| 		iJack = find_usb_ijack(hostif, jack_id); | ||||
| 		if (iJack != 0) { | ||||
| 			res = usb_string(umidi->dev, iJack, jack_name_buf, | ||||
| 			  ARRAY_SIZE(jack_name_buf)); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds