Pull sound fixes from Takashi Iwai: "Hopefully the last one for 6.2, a collection of the fixes that have been gathered since the last pull. All changes are small and trivial device-specific fixes" * tag 'sound-6.2-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda/realtek: Add Positivo N14KP6-TG ASoC: topology: Return -ENOMEM on memory allocation failure ALSA: emux: Avoid potential array out-of-bound in snd_emux_xg_control() ASoC: fsl_sai: fix getting version from VERID ALSA: hda/realtek: fix mute/micmute LEDs don't work for a HP platform. ALSA: hda/realtek: Add quirk for ASUS UM3402 using CS35L41 ASoC: codecs: es8326: Fix DTS properties reading ASoC: tas5805m: add missing page switch. ASoC: tas5805m: rework to avoid scheduling while atomic. ALSA: hda/realtek: Enable mute/micmute LEDs on HP Elitebook, 645 G9 ASoC: SOF: amd: Fix for handling spurious interrupts from DSP ALSA: hda/realtek: Fix the speaker output on Samsung Galaxy Book2 Pro 360 ALSA: pci: lx6464es: fix a debug loop ASoC: rt715-sdca: fix clock stop prepare timeout issue
Unified · Split
| @@ -9423,6 +9423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 9422 unmodified lines | |||
| 9423 | SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), | 9423 | SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), |
| 9424 | SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | 9424 | SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9425 | SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | 9425 | SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9426 | SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | ||
| 9426 | SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), | 9427 | SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), |
| 9427 | SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED), | 9428 | SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED), |
| 9428 | SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), | 9429 | SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), |
| @@ -9433,6 +9434,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 4 unmodified lines | |||
| 9433 | SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | 9434 | SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9434 | SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | 9435 | SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9435 | SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), | 9436 | SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9437 | SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED), | ||
| 9438 | SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED), | ||
| 9439 | SND_PCI_QUIRK(0x103c, 0x8b8a, "HP", ALC236_FIXUP_HP_GPIO_LED), | ||
| 9440 | SND_PCI_QUIRK(0x103c, 0x8b8b, "HP", ALC236_FIXUP_HP_GPIO_LED), | ||
| 9441 | SND_PCI_QUIRK(0x103c, 0x8b8d, "HP", ALC236_FIXUP_HP_GPIO_LED), | ||
| 9436 | SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | 9442 | SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9437 | SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), | 9443 | SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), |
| 9438 | SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), | 9444 | SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), |
| @@ -9480,6 +9486,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 41 unmodified lines | |||
| 9480 | SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), | 9486 | SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), |
| 9481 | SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2), | 9487 | SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2), |
| 9482 | SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), | 9488 | SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), |
| 9489 | SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), | ||
| 9483 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), | 9490 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), |
| 9484 | SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), | 9491 | SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), |
| 9485 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), | 9492 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), |
| @@ -9523,6 +9530,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 37 unmodified lines | |||
| 9523 | SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP), | 9530 | SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP), |
| 9524 | SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP), | 9531 | SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP), |
| 9525 | SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), | 9532 | SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), |
| 9533 | SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP), | ||
| 9526 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), | 9534 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), |
| 9527 | SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), | 9535 | SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), |
| 9528 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), | 9536 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), |
| @@ -9701,6 +9709,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 172 unmodified lines | |||
| 9701 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ | 9709 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ |
| 9702 | SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), | 9710 | SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), |
| 9703 | SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), | 9711 | SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), |
| 9712 | SND_PCI_QUIRK(0x1c6c, 0x1251, "Positivo N14KP6-TG", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
| 9704 | SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), | 9713 | SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), |
| 9705 | SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP), | 9714 | SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP), |
| 9706 | SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP), | 9715 | SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP), |
| @@ -493,12 +493,11 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, · 492 unmodified lines | |||
| 493 | dev_dbg(chip->card->dev, | 493 | dev_dbg(chip->card->dev, |
| 494 | "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", | 494 | "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", |
| 495 | *r_needed, *r_freed); | 495 | *r_needed, *r_freed); |
| 496 | for (i = 0; i < MAX_STREAM_BUFFER; ++i) { | 496 | for (i = 0; i < MAX_STREAM_BUFFER && i < chip->rmh.stat_len; |
| 497 | for (i = 0; i != chip->rmh.stat_len; ++i) | 497 | ++i) { |
| 498 | dev_dbg(chip->card->dev, | 498 | dev_dbg(chip->card->dev, " stat[%d]: %x, %x\n", i, |
| 499 | " stat[%d]: %x, %x\n", i, | 499 | chip->rmh.stat[i], |
| 500 | chip->rmh.stat[i], | 500 | chip->rmh.stat[i] & MASK_DATA_SIZE); |
| 501 | chip->rmh.stat[i] & MASK_DATA_SIZE); | ||
| 502 | } | 501 | } |
| 503 | } | 502 | } |
| 504 | 503 | ||
| @@ -729,14 +729,16 @@ static int es8326_probe(struct snd_soc_component *component) · 728 unmodified lines | |||
| 729 | } | 729 | } |
| 730 | dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol); | 730 | dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol); |
| 731 | 731 | ||
| 732 | ret = device_property_read_u8(component->dev, "everest,interrupt-src", &es8326->jack_pol); | 732 | ret = device_property_read_u8(component->dev, "everest,interrupt-src", |
| 733 | &es8326->interrupt_src); | ||
| 733 | if (ret != 0) { | 734 | if (ret != 0) { |
| 734 | dev_dbg(component->dev, "interrupt-src return %d", ret); | 735 | dev_dbg(component->dev, "interrupt-src return %d", ret); |
| 735 | es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9; | 736 | es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9; |
| 736 | } | 737 | } |
| 737 | dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src); | 738 | dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src); |
| 738 | 739 | ||
| 739 | ret = device_property_read_u8(component->dev, "everest,interrupt-clk", &es8326->jack_pol); | 740 | ret = device_property_read_u8(component->dev, "everest,interrupt-clk", |
| 741 | &es8326->interrupt_clk); | ||
| 740 | if (ret != 0) { | 742 | if (ret != 0) { |
| 741 | dev_dbg(component->dev, "interrupt-clk return %d", ret); | 743 | dev_dbg(component->dev, "interrupt-clk return %d", ret); |
| 742 | es8326->interrupt_clk = 0x45; | 744 | es8326->interrupt_clk = 0x45; |
| @@ -167,7 +167,7 @@ static int rt715_sdca_read_prop(struct sdw_slave *slave) · 166 unmodified lines | |||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | /* set the timeout values */ | 169 | /* set the timeout values */ |
| 170 | prop->clk_stop_timeout = 20; | 170 | prop->clk_stop_timeout = 200; |
| 171 | 171 | ||
| 172 | return 0; | 172 | return 0; |
| 173 | } | 173 | } |
| @@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = { · 153 unmodified lines | |||
| 154 | #define TAS5805M_VOLUME_MIN 0 | 154 | #define TAS5805M_VOLUME_MIN 0 |
| 155 | 155 | ||
| 156 | struct tas5805m_priv { | 156 | struct tas5805m_priv { |
| 157 | struct i2c_client *i2c; | ||
| 157 | struct regulator *pvdd; | 158 | struct regulator *pvdd; |
| 158 | struct gpio_desc *gpio_pdn_n; | 159 | struct gpio_desc *gpio_pdn_n; |
| 159 | 160 | ||
| @@ -165,6 +166,9 @@ struct tas5805m_priv { · 5 unmodified lines | |||
| 165 | int vol[2]; | 166 | int vol[2]; |
| 166 | bool is_powered; | 167 | bool is_powered; |
| 167 | bool is_muted; | 168 | bool is_muted; |
| 169 | |||
| 170 | struct work_struct work; | ||
| 171 | struct mutex lock; | ||
| 168 | }; | 172 | }; |
| 169 | 173 | ||
| 170 | static void set_dsp_scale(struct regmap *rm, int offset, int vol) | 174 | static void set_dsp_scale(struct regmap *rm, int offset, int vol) |
| @@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offset, int vol) · 10 unmodified lines | |||
| 181 | regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v)); | 185 | regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v)); |
| 182 | } | 186 | } |
| 183 | 187 | ||
| 184 | static void tas5805m_refresh(struct snd_soc_component *component) | 188 | static void tas5805m_refresh(struct tas5805m_priv *tas5805m) |
| 185 | { | 189 | { |
| 186 | struct tas5805m_priv *tas5805m = | ||
| 187 | snd_soc_component_get_drvdata(component); | ||
| 188 | struct regmap *rm = tas5805m->regmap; | 190 | struct regmap *rm = tas5805m->regmap; |
| 189 | 191 | ||
| 190 | dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n", | 192 | dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=%d, vol=%d/%d\n", |
| 191 | tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]); | 193 | tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]); |
| 192 | 194 | ||
| 193 | regmap_write(rm, REG_PAGE, 0x00); | 195 | regmap_write(rm, REG_PAGE, 0x00); |
| @@ -201,6 +203,9 @@ static void tas5805m_refresh(struct snd_soc_component *component) · 7 unmodified lines | |||
| 201 | set_dsp_scale(rm, 0x24, tas5805m->vol[0]); | 203 | set_dsp_scale(rm, 0x24, tas5805m->vol[0]); |
| 202 | set_dsp_scale(rm, 0x28, tas5805m->vol[1]); | 204 | set_dsp_scale(rm, 0x28, tas5805m->vol[1]); |
| 203 | 205 | ||
| 206 | regmap_write(rm, REG_PAGE, 0x00); | ||
| 207 | regmap_write(rm, REG_BOOK, 0x00); | ||
| 208 | |||
| 204 | /* Set/clear digital soft-mute */ | 209 | /* Set/clear digital soft-mute */ |
| 205 | regmap_write(rm, REG_DEVICE_CTRL_2, | 210 | regmap_write(rm, REG_DEVICE_CTRL_2, |
| 206 | (tas5805m->is_muted ? DCTRL2_MUTE : 0) | | 211 | (tas5805m->is_muted ? DCTRL2_MUTE : 0) | |
| @@ -226,8 +231,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol, · 19 unmodified lines | |||
| 226 | struct tas5805m_priv *tas5805m = | 231 | struct tas5805m_priv *tas5805m = |
| 227 | snd_soc_component_get_drvdata(component); | 232 | snd_soc_component_get_drvdata(component); |
| 228 | 233 | ||
| 234 | mutex_lock(&tas5805m->lock); | ||
| 229 | ucontrol->value.integer.value[0] = tas5805m->vol[0]; | 235 | ucontrol->value.integer.value[0] = tas5805m->vol[0]; |
| 230 | ucontrol->value.integer.value[1] = tas5805m->vol[1]; | 236 | ucontrol->value.integer.value[1] = tas5805m->vol[1]; |
| 237 | mutex_unlock(&tas5805m->lock); | ||
| 238 | |||
| 231 | return 0; | 239 | return 0; |
| 232 | } | 240 | } |
| 233 | 241 | ||
| @@ -243,11 +251,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol, · 9 unmodified lines | |||
| 243 | snd_soc_kcontrol_component(kcontrol); | 251 | snd_soc_kcontrol_component(kcontrol); |
| 244 | struct tas5805m_priv *tas5805m = | 252 | struct tas5805m_priv *tas5805m = |
| 245 | snd_soc_component_get_drvdata(component); | 253 | snd_soc_component_get_drvdata(component); |
| 254 | int ret = 0; | ||
| 246 | 255 | ||
| 247 | if (!(volume_is_valid(ucontrol->value.integer.value[0]) && | 256 | if (!(volume_is_valid(ucontrol->value.integer.value[0]) && |
| 248 | volume_is_valid(ucontrol->value.integer.value[1]))) | 257 | volume_is_valid(ucontrol->value.integer.value[1]))) |
| 249 | return -EINVAL; | 258 | return -EINVAL; |
| 250 | 259 | ||
| 260 | mutex_lock(&tas5805m->lock); | ||
| 251 | if (tas5805m->vol[0] != ucontrol->value.integer.value[0] || | 261 | if (tas5805m->vol[0] != ucontrol->value.integer.value[0] || |
| 252 | tas5805m->vol[1] != ucontrol->value.integer.value[1]) { | 262 | tas5805m->vol[1] != ucontrol->value.integer.value[1]) { |
| 253 | tas5805m->vol[0] = ucontrol->value.integer.value[0]; | 263 | tas5805m->vol[0] = ucontrol->value.integer.value[0]; |
| @@ -256,11 +266,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol, · 2 unmodified lines | |||
| 256 | tas5805m->vol[0], tas5805m->vol[1], | 266 | tas5805m->vol[0], tas5805m->vol[1], |
| 257 | tas5805m->is_powered); | 267 | tas5805m->is_powered); |
| 258 | if (tas5805m->is_powered) | 268 | if (tas5805m->is_powered) |
| 259 | tas5805m_refresh(component); | 269 | tas5805m_refresh(tas5805m); |
| 260 | return 1; | 270 | ret = 1; |
| 261 | } | 271 | } |
| 272 | mutex_unlock(&tas5805m->lock); | ||
| 262 | 273 | ||
| 263 | return 0; | 274 | return ret; |
| 264 | } | 275 | } |
| 265 | 276 | ||
| 266 | static const struct snd_kcontrol_new tas5805m_snd_controls[] = { | 277 | static const struct snd_kcontrol_new tas5805m_snd_controls[] = { |
| @@ -294,54 +305,83 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, · 27 unmodified lines | |||
| 294 | struct snd_soc_component *component = dai->component; | 305 | struct snd_soc_component *component = dai->component; |
| 295 | struct tas5805m_priv *tas5805m = | 306 | struct tas5805m_priv *tas5805m = |
| 296 | snd_soc_component_get_drvdata(component); | 307 | snd_soc_component_get_drvdata(component); |
| 297 | struct regmap *rm = tas5805m->regmap; | ||
| 298 | unsigned int chan, global1, global2; | ||
| 299 | 308 | ||
| 300 | switch (cmd) { | 309 | switch (cmd) { |
| 301 | case SNDRV_PCM_TRIGGER_START: | 310 | case SNDRV_PCM_TRIGGER_START: |
| 302 | case SNDRV_PCM_TRIGGER_RESUME: | 311 | case SNDRV_PCM_TRIGGER_RESUME: |
| 303 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 312 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 304 | dev_dbg(component->dev, "DSP startup\n"); | 313 | dev_dbg(component->dev, "clock start\n"); |
| 305 | 314 | schedule_work(&tas5805m->work); | |
| 306 | /* We mustn't issue any I2C transactions until the I2S | ||
| 307 | * clock is stable. Furthermore, we must allow a 5ms | ||
| 308 | * delay after the first set of register writes to | ||
| 309 | * allow the DSP to boot before configuring it. | ||
| 310 | */ | ||
| 311 | usleep_range(5000, 10000); | ||
| 312 | send_cfg(rm, dsp_cfg_preboot, | ||
| 313 | ARRAY_SIZE(dsp_cfg_preboot)); | ||
| 314 | usleep_range(5000, 15000); | ||
| 315 | send_cfg(rm, tas5805m->dsp_cfg_data, | ||
| 316 | tas5805m->dsp_cfg_len); | ||
| 317 | |||
| 318 | tas5805m->is_powered = true; | ||
| 319 | tas5805m_refresh(component); | ||
| 320 | break; | 315 | break; |
| 321 | 316 | ||
| 322 | case SNDRV_PCM_TRIGGER_STOP: | 317 | case SNDRV_PCM_TRIGGER_STOP: |
| 323 | case SNDRV_PCM_TRIGGER_SUSPEND: | 318 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 324 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 319 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 325 | dev_dbg(component->dev, "DSP shutdown\n"); | 320 | break; |
| 326 | 321 | ||
| 327 | tas5805m->is_powered = false; | 322 | default: |
| 323 | return -EINVAL; | ||
| 324 | } | ||
| 328 | 325 | ||
| 329 | regmap_write(rm, REG_PAGE, 0x00); | 326 | return 0; |
| 330 | regmap_write(rm, REG_BOOK, 0x00); | 327 | } |
| 331 | 328 | ||
| 332 | regmap_read(rm, REG_CHAN_FAULT, &chan); | 329 | static void do_work(struct work_struct *work) |
| 333 | regmap_read(rm, REG_GLOBAL_FAULT1, &global1); | 330 | { |
| 334 | regmap_read(rm, REG_GLOBAL_FAULT2, &global2); | 331 | struct tas5805m_priv *tas5805m = |
| 332 | container_of(work, struct tas5805m_priv, work); | ||
| 333 | struct regmap *rm = tas5805m->regmap; | ||
| 335 | 334 | ||
| 336 | dev_dbg(component->dev, | 335 | dev_dbg(&tas5805m->i2c->dev, "DSP startup\n"); |
| 337 | "fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n", | ||
| 338 | chan, global1, global2); | ||
| 339 | 336 | ||
| 340 | regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ); | 337 | mutex_lock(&tas5805m->lock); |
| 341 | break; | 338 | /* We mustn't issue any I2C transactions until the I2S |
| 339 | * clock is stable. Furthermore, we must allow a 5ms | ||
| 340 | * delay after the first set of register writes to | ||
| 341 | * allow the DSP to boot before configuring it. | ||
| 342 | */ | ||
| 343 | usleep_range(5000, 10000); | ||
| 344 | send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot)); | ||
| 345 | usleep_range(5000, 15000); | ||
| 346 | send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len); | ||
| 347 | |||
| 348 | tas5805m->is_powered = true; | ||
| 349 | tas5805m_refresh(tas5805m); | ||
| 350 | mutex_unlock(&tas5805m->lock); | ||
| 351 | } | ||
| 342 | 352 | ||
| 343 | default: | 353 | static int tas5805m_dac_event(struct snd_soc_dapm_widget *w, |
| 344 | return -EINVAL; | 354 | struct snd_kcontrol *kcontrol, int event) |
| 355 | { | ||
| 356 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
| 357 | struct tas5805m_priv *tas5805m = | ||
| 358 | snd_soc_component_get_drvdata(component); | ||
| 359 | struct regmap *rm = tas5805m->regmap; | ||
| 360 | |||
| 361 | if (event & SND_SOC_DAPM_PRE_PMD) { | ||
| 362 | unsigned int chan, global1, global2; | ||
| 363 | |||
| 364 | dev_dbg(component->dev, "DSP shutdown\n"); | ||
| 365 | cancel_work_sync(&tas5805m->work); | ||
| 366 | |||
| 367 | mutex_lock(&tas5805m->lock); | ||
| 368 | if (tas5805m->is_powered) { | ||
| 369 | tas5805m->is_powered = false; | ||
| 370 | |||
| 371 | regmap_write(rm, REG_PAGE, 0x00); | ||
| 372 | regmap_write(rm, REG_BOOK, 0x00); | ||
| 373 | |||
| 374 | regmap_read(rm, REG_CHAN_FAULT, &chan); | ||
| 375 | regmap_read(rm, REG_GLOBAL_FAULT1, &global1); | ||
| 376 | regmap_read(rm, REG_GLOBAL_FAULT2, &global2); | ||
| 377 | |||
| 378 | dev_dbg(component->dev, "fault regs: CHAN=%02x, " | ||
| 379 | "GLOBAL1=%02x, GLOBAL2=%02x\n", | ||
| 380 | chan, global1, global2); | ||
| 381 | |||
| 382 | regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ); | ||
| 383 | } | ||
| 384 | mutex_unlock(&tas5805m->lock); | ||
| 345 | } | 385 | } |
| 346 | 386 | ||
| 347 | return 0; | 387 | return 0; |
| @@ -354,7 +394,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = { · 6 unmodified lines | |||
| 354 | 394 | ||
| 355 | static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = { | 395 | static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = { |
| 356 | SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), | 396 | SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), |
| 357 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | 397 | SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, |
| 398 | tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD), | ||
| 358 | SND_SOC_DAPM_OUTPUT("OUT") | 399 | SND_SOC_DAPM_OUTPUT("OUT") |
| 359 | }; | 400 | }; |
| 360 | 401 | ||
| @@ -375,11 +416,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction) · 14 unmodified lines | |||
| 375 | struct tas5805m_priv *tas5805m = | 416 | struct tas5805m_priv *tas5805m = |
| 376 | snd_soc_component_get_drvdata(component); | 417 | snd_soc_component_get_drvdata(component); |
| 377 | 418 | ||
| 419 | mutex_lock(&tas5805m->lock); | ||
| 378 | dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n", | 420 | dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n", |
| 379 | mute, tas5805m->is_powered); | 421 | mute, tas5805m->is_powered); |
| 422 | |||
| 380 | tas5805m->is_muted = mute; | 423 | tas5805m->is_muted = mute; |
| 381 | if (tas5805m->is_powered) | 424 | if (tas5805m->is_powered) |
| 382 | tas5805m_refresh(component); | 425 | tas5805m_refresh(tas5805m); |
| 426 | mutex_unlock(&tas5805m->lock); | ||
| 383 | 427 | ||
| 384 | return 0; | 428 | return 0; |
| 385 | } | 429 | } |
| @@ -434,6 +478,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) · 48 unmodified lines | |||
| 434 | if (!tas5805m) | 478 | if (!tas5805m) |
| 435 | return -ENOMEM; | 479 | return -ENOMEM; |
| 436 | 480 | ||
| 481 | tas5805m->i2c = i2c; | ||
| 437 | tas5805m->pvdd = devm_regulator_get(dev, "pvdd"); | 482 | tas5805m->pvdd = devm_regulator_get(dev, "pvdd"); |
| 438 | if (IS_ERR(tas5805m->pvdd)) { | 483 | if (IS_ERR(tas5805m->pvdd)) { |
| 439 | dev_err(dev, "failed to get pvdd supply: %ld\n", | 484 | dev_err(dev, "failed to get pvdd supply: %ld\n", |
| @@ -507,6 +552,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) · 67 unmodified lines | |||
| 507 | gpiod_set_value(tas5805m->gpio_pdn_n, 1); | 552 | gpiod_set_value(tas5805m->gpio_pdn_n, 1); |
| 508 | usleep_range(10000, 15000); | 553 | usleep_range(10000, 15000); |
| 509 | 554 | ||
| 555 | INIT_WORK(&tas5805m->work, do_work); | ||
| 556 | mutex_init(&tas5805m->lock); | ||
| 557 | |||
| 510 | /* Don't register through devm. We need to be able to unregister | 558 | /* Don't register through devm. We need to be able to unregister |
| 511 | * the component prior to deasserting PDN# | 559 | * the component prior to deasserting PDN# |
| 512 | */ | 560 | */ |
| @@ -527,6 +575,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c) · 14 unmodified lines | |||
| 527 | struct device *dev = &i2c->dev; | 575 | struct device *dev = &i2c->dev; |
| 528 | struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); | 576 | struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); |
| 529 | 577 | ||
| 578 | cancel_work_sync(&tas5805m->work); | ||
| 530 | snd_soc_unregister_component(dev); | 579 | snd_soc_unregister_component(dev); |
| 531 | gpiod_set_value(tas5805m->gpio_pdn_n, 0); | 580 | gpiod_set_value(tas5805m->gpio_pdn_n, 0); |
| 532 | usleep_range(10000, 15000); | 581 | usleep_range(10000, 15000); |
| @@ -1141,6 +1141,7 @@ static int fsl_sai_check_version(struct device *dev) · 1140 unmodified lines | |||
| 1141 | 1141 | ||
| 1142 | sai->verid.version = val & | 1142 | sai->verid.version = val & |
| 1143 | (FSL_SAI_VERID_MAJOR_MASK | FSL_SAI_VERID_MINOR_MASK); | 1143 | (FSL_SAI_VERID_MAJOR_MASK | FSL_SAI_VERID_MINOR_MASK); |
| 1144 | sai->verid.version >>= FSL_SAI_VERID_MINOR_SHIFT; | ||
| 1144 | sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK; | 1145 | sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK; |
| 1145 | 1146 | ||
| 1146 | ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val); | 1147 | ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val); |
| @@ -1401,13 +1401,17 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, · 1400 unmodified lines | |||
| 1401 | 1401 | ||
| 1402 | template.num_kcontrols = le32_to_cpu(w->num_kcontrols); | 1402 | template.num_kcontrols = le32_to_cpu(w->num_kcontrols); |
| 1403 | kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); | 1403 | kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); |
| 1404 | if (!kc) | 1404 | if (!kc) { |
| 1405 | ret = -ENOMEM; | ||
| 1405 | goto hdr_err; | 1406 | goto hdr_err; |
| 1407 | } | ||
| 1406 | 1408 | ||
| 1407 | kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), | 1409 | kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), |
| 1408 | GFP_KERNEL); | 1410 | GFP_KERNEL); |
| 1409 | if (!kcontrol_type) | 1411 | if (!kcontrol_type) { |
| 1412 | ret = -ENOMEM; | ||
| 1410 | goto hdr_err; | 1413 | goto hdr_err; |
| 1414 | } | ||
| 1411 | 1415 | ||
| 1412 | for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { | 1416 | for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { |
| 1413 | control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; | 1417 | control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; |
| @@ -318,7 +318,6 @@ static irqreturn_t acp_irq_thread(int irq, void *context) · 317 unmodified lines | |||
| 318 | { | 318 | { |
| 319 | struct snd_sof_dev *sdev = context; | 319 | struct snd_sof_dev *sdev = context; |
| 320 | const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); | 320 | const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); |
| 321 | unsigned int base = desc->dsp_intr_base; | ||
| 322 | unsigned int val, count = ACP_HW_SEM_RETRY_COUNT; | 321 | unsigned int val, count = ACP_HW_SEM_RETRY_COUNT; |
| 323 | 322 | ||
| 324 | val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat); | 323 | val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat); |
| @@ -328,28 +327,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context) · 3 unmodified lines | |||
| 328 | return IRQ_HANDLED; | 327 | return IRQ_HANDLED; |
| 329 | } | 328 | } |
| 330 | 329 | ||
| 331 | val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); | 330 | while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { |
| 332 | if (val & ACP_DSP_TO_HOST_IRQ) { | 331 | /* Wait until acquired HW Semaphore lock or timeout */ |
| 333 | while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { | 332 | count--; |
| 334 | /* Wait until acquired HW Semaphore lock or timeout */ | 333 | if (!count) { |
| 335 | count--; | 334 | dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); |
| 336 | if (!count) { | 335 | return IRQ_NONE; |
| 337 | dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); | ||
| 338 | return IRQ_NONE; | ||
| 339 | } | ||
| 340 | } | 336 | } |
| 341 | |||
| 342 | sof_ops(sdev)->irq_thread(irq, sdev); | ||
| 343 | val |= ACP_DSP_TO_HOST_IRQ; | ||
| 344 | snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val); | ||
| 345 | |||
| 346 | /* Unlock or Release HW Semaphore */ | ||
| 347 | snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0); | ||
| 348 | |||
| 349 | return IRQ_HANDLED; | ||
| 350 | } | 337 | } |
| 351 | 338 | ||
| 352 | return IRQ_NONE; | 339 | sof_ops(sdev)->irq_thread(irq, sdev); |
| 340 | /* Unlock or Release HW Semaphore */ | ||
| 341 | snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0); | ||
| 342 | |||
| 343 | return IRQ_HANDLED; | ||
| 353 | }; | 344 | }; |
| 354 | 345 | ||
| 355 | static irqreturn_t acp_irq_handler(int irq, void *dev_id) | 346 | static irqreturn_t acp_irq_handler(int irq, void *dev_id) |
| @@ -360,8 +351,11 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id) · 4 unmodified lines | |||
| 360 | unsigned int val; | 351 | unsigned int val; |
| 361 | 352 | ||
| 362 | val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); | 353 | val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); |
| 363 | if (val) | 354 | if (val) { |
| 355 | val |= ACP_DSP_TO_HOST_IRQ; | ||
| 356 | snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val); | ||
| 364 | return IRQ_WAKE_THREAD; | 357 | return IRQ_WAKE_THREAD; |
| 358 | } | ||
| 365 | 359 | ||
| 366 | return IRQ_NONE; | 360 | return IRQ_NONE; |
| 367 | } | 361 | } |
| @@ -349,6 +349,9 @@ int · 348 unmodified lines | |||
| 349 | snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan, | 349 | snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan, |
| 350 | int param) | 350 | int param) |
| 351 | { | 351 | { |
| 352 | if (param >= ARRAY_SIZE(chan->control)) | ||
| 353 | return -EINVAL; | ||
| 354 | |||
| 352 | return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects), | 355 | return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects), |
| 353 | port, chan, param, | 356 | port, chan, param, |
| 354 | chan->control[param], | 357 | chan->control[param], |