Commit 4fe37223 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-6.2-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

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
parents 38c1e0c6 88d18b88
...@@ -9423,6 +9423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9423,6 +9423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), 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[] = { ...@@ -9433,6 +9434,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
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, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", 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, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b8a, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b8b, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b8d, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
...@@ -9480,6 +9486,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9480,6 +9486,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
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, 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, 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, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
...@@ -9523,6 +9530,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9523,6 +9530,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP), SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP), SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), 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[] = { ...@@ -9701,6 +9709,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
SND_PCI_QUIRK(0x1c6c, 0x1251, "Positivo N14KP6-TG", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS),
SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP), 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, ...@@ -493,12 +493,11 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
dev_dbg(chip->card->dev, dev_dbg(chip->card->dev,
"CMD_08_ASK_BUFFERS: needed %d, freed %d\n", "CMD_08_ASK_BUFFERS: needed %d, freed %d\n",
*r_needed, *r_freed); *r_needed, *r_freed);
for (i = 0; i < MAX_STREAM_BUFFER; ++i) { for (i = 0; i < MAX_STREAM_BUFFER && i < chip->rmh.stat_len;
for (i = 0; i != chip->rmh.stat_len; ++i) ++i) {
dev_dbg(chip->card->dev, dev_dbg(chip->card->dev, " stat[%d]: %x, %x\n", i,
" stat[%d]: %x, %x\n", i, chip->rmh.stat[i],
chip->rmh.stat[i], chip->rmh.stat[i] & MASK_DATA_SIZE);
chip->rmh.stat[i] & MASK_DATA_SIZE);
} }
} }
......
...@@ -729,14 +729,16 @@ static int es8326_probe(struct snd_soc_component *component) ...@@ -729,14 +729,16 @@ static int es8326_probe(struct snd_soc_component *component)
} }
dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol); dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol);
ret = device_property_read_u8(component->dev, "everest,interrupt-src", &es8326->jack_pol); ret = device_property_read_u8(component->dev, "everest,interrupt-src",
&es8326->interrupt_src);
if (ret != 0) { if (ret != 0) {
dev_dbg(component->dev, "interrupt-src return %d", ret); dev_dbg(component->dev, "interrupt-src return %d", ret);
es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9; es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9;
} }
dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src); dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src);
ret = device_property_read_u8(component->dev, "everest,interrupt-clk", &es8326->jack_pol); ret = device_property_read_u8(component->dev, "everest,interrupt-clk",
&es8326->interrupt_clk);
if (ret != 0) { if (ret != 0) {
dev_dbg(component->dev, "interrupt-clk return %d", ret); dev_dbg(component->dev, "interrupt-clk return %d", ret);
es8326->interrupt_clk = 0x45; es8326->interrupt_clk = 0x45;
......
...@@ -167,7 +167,7 @@ static int rt715_sdca_read_prop(struct sdw_slave *slave) ...@@ -167,7 +167,7 @@ static int rt715_sdca_read_prop(struct sdw_slave *slave)
} }
/* set the timeout values */ /* set the timeout values */
prop->clk_stop_timeout = 20; prop->clk_stop_timeout = 200;
return 0; return 0;
} }
......
...@@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = { ...@@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = {
#define TAS5805M_VOLUME_MIN 0 #define TAS5805M_VOLUME_MIN 0
struct tas5805m_priv { struct tas5805m_priv {
struct i2c_client *i2c;
struct regulator *pvdd; struct regulator *pvdd;
struct gpio_desc *gpio_pdn_n; struct gpio_desc *gpio_pdn_n;
...@@ -165,6 +166,9 @@ struct tas5805m_priv { ...@@ -165,6 +166,9 @@ struct tas5805m_priv {
int vol[2]; int vol[2];
bool is_powered; bool is_powered;
bool is_muted; bool is_muted;
struct work_struct work;
struct mutex lock;
}; };
static void set_dsp_scale(struct regmap *rm, int offset, int vol) 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) ...@@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offset, int vol)
regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v)); regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v));
} }
static void tas5805m_refresh(struct snd_soc_component *component) static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
{ {
struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component);
struct regmap *rm = tas5805m->regmap; struct regmap *rm = tas5805m->regmap;
dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n", dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=%d, vol=%d/%d\n",
tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]); tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]);
regmap_write(rm, REG_PAGE, 0x00); regmap_write(rm, REG_PAGE, 0x00);
...@@ -201,6 +203,9 @@ static void tas5805m_refresh(struct snd_soc_component *component) ...@@ -201,6 +203,9 @@ static void tas5805m_refresh(struct snd_soc_component *component)
set_dsp_scale(rm, 0x24, tas5805m->vol[0]); set_dsp_scale(rm, 0x24, tas5805m->vol[0]);
set_dsp_scale(rm, 0x28, tas5805m->vol[1]); set_dsp_scale(rm, 0x28, tas5805m->vol[1]);
regmap_write(rm, REG_PAGE, 0x00);
regmap_write(rm, REG_BOOK, 0x00);
/* Set/clear digital soft-mute */ /* Set/clear digital soft-mute */
regmap_write(rm, REG_DEVICE_CTRL_2, regmap_write(rm, REG_DEVICE_CTRL_2,
(tas5805m->is_muted ? DCTRL2_MUTE : 0) | (tas5805m->is_muted ? DCTRL2_MUTE : 0) |
...@@ -226,8 +231,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol, ...@@ -226,8 +231,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol,
struct tas5805m_priv *tas5805m = struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
mutex_lock(&tas5805m->lock);
ucontrol->value.integer.value[0] = tas5805m->vol[0]; ucontrol->value.integer.value[0] = tas5805m->vol[0];
ucontrol->value.integer.value[1] = tas5805m->vol[1]; ucontrol->value.integer.value[1] = tas5805m->vol[1];
mutex_unlock(&tas5805m->lock);
return 0; return 0;
} }
...@@ -243,11 +251,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol, ...@@ -243,11 +251,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
snd_soc_kcontrol_component(kcontrol); snd_soc_kcontrol_component(kcontrol);
struct tas5805m_priv *tas5805m = struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
int ret = 0;
if (!(volume_is_valid(ucontrol->value.integer.value[0]) && if (!(volume_is_valid(ucontrol->value.integer.value[0]) &&
volume_is_valid(ucontrol->value.integer.value[1]))) volume_is_valid(ucontrol->value.integer.value[1])))
return -EINVAL; return -EINVAL;
mutex_lock(&tas5805m->lock);
if (tas5805m->vol[0] != ucontrol->value.integer.value[0] || if (tas5805m->vol[0] != ucontrol->value.integer.value[0] ||
tas5805m->vol[1] != ucontrol->value.integer.value[1]) { tas5805m->vol[1] != ucontrol->value.integer.value[1]) {
tas5805m->vol[0] = ucontrol->value.integer.value[0]; tas5805m->vol[0] = ucontrol->value.integer.value[0];
...@@ -256,11 +266,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol, ...@@ -256,11 +266,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
tas5805m->vol[0], tas5805m->vol[1], tas5805m->vol[0], tas5805m->vol[1],
tas5805m->is_powered); tas5805m->is_powered);
if (tas5805m->is_powered) if (tas5805m->is_powered)
tas5805m_refresh(component); tas5805m_refresh(tas5805m);
return 1; ret = 1;
} }
mutex_unlock(&tas5805m->lock);
return 0; return ret;
} }
static const struct snd_kcontrol_new tas5805m_snd_controls[] = { static const struct snd_kcontrol_new tas5805m_snd_controls[] = {
...@@ -294,54 +305,83 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -294,54 +305,83 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct tas5805m_priv *tas5805m = struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
struct regmap *rm = tas5805m->regmap;
unsigned int chan, global1, global2;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dev_dbg(component->dev, "DSP startup\n"); dev_dbg(component->dev, "clock start\n");
schedule_work(&tas5805m->work);
/* We mustn't issue any I2C transactions until the I2S
* clock is stable. Furthermore, we must allow a 5ms
* delay after the first set of register writes to
* allow the DSP to boot before configuring it.
*/
usleep_range(5000, 10000);
send_cfg(rm, dsp_cfg_preboot,
ARRAY_SIZE(dsp_cfg_preboot));
usleep_range(5000, 15000);
send_cfg(rm, tas5805m->dsp_cfg_data,
tas5805m->dsp_cfg_len);
tas5805m->is_powered = true;
tas5805m_refresh(component);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dev_dbg(component->dev, "DSP shutdown\n"); break;
tas5805m->is_powered = false; default:
return -EINVAL;
}
regmap_write(rm, REG_PAGE, 0x00); return 0;
regmap_write(rm, REG_BOOK, 0x00); }
regmap_read(rm, REG_CHAN_FAULT, &chan); static void do_work(struct work_struct *work)
regmap_read(rm, REG_GLOBAL_FAULT1, &global1); {
regmap_read(rm, REG_GLOBAL_FAULT2, &global2); struct tas5805m_priv *tas5805m =
container_of(work, struct tas5805m_priv, work);
struct regmap *rm = tas5805m->regmap;
dev_dbg(component->dev, dev_dbg(&tas5805m->i2c->dev, "DSP startup\n");
"fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n",
chan, global1, global2);
regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ); mutex_lock(&tas5805m->lock);
break; /* We mustn't issue any I2C transactions until the I2S
* clock is stable. Furthermore, we must allow a 5ms
* delay after the first set of register writes to
* allow the DSP to boot before configuring it.
*/
usleep_range(5000, 10000);
send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot));
usleep_range(5000, 15000);
send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len);
tas5805m->is_powered = true;
tas5805m_refresh(tas5805m);
mutex_unlock(&tas5805m->lock);
}
default: static int tas5805m_dac_event(struct snd_soc_dapm_widget *w,
return -EINVAL; struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component);
struct regmap *rm = tas5805m->regmap;
if (event & SND_SOC_DAPM_PRE_PMD) {
unsigned int chan, global1, global2;
dev_dbg(component->dev, "DSP shutdown\n");
cancel_work_sync(&tas5805m->work);
mutex_lock(&tas5805m->lock);
if (tas5805m->is_powered) {
tas5805m->is_powered = false;
regmap_write(rm, REG_PAGE, 0x00);
regmap_write(rm, REG_BOOK, 0x00);
regmap_read(rm, REG_CHAN_FAULT, &chan);
regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
dev_dbg(component->dev, "fault regs: CHAN=%02x, "
"GLOBAL1=%02x, GLOBAL2=%02x\n",
chan, global1, global2);
regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
}
mutex_unlock(&tas5805m->lock);
} }
return 0; return 0;
...@@ -354,7 +394,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = { ...@@ -354,7 +394,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = { static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("OUT") SND_SOC_DAPM_OUTPUT("OUT")
}; };
...@@ -375,11 +416,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction) ...@@ -375,11 +416,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction)
struct tas5805m_priv *tas5805m = struct tas5805m_priv *tas5805m =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
mutex_lock(&tas5805m->lock);
dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n", dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n",
mute, tas5805m->is_powered); mute, tas5805m->is_powered);
tas5805m->is_muted = mute; tas5805m->is_muted = mute;
if (tas5805m->is_powered) if (tas5805m->is_powered)
tas5805m_refresh(component); tas5805m_refresh(tas5805m);
mutex_unlock(&tas5805m->lock);
return 0; return 0;
} }
...@@ -434,6 +478,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) ...@@ -434,6 +478,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
if (!tas5805m) if (!tas5805m)
return -ENOMEM; return -ENOMEM;
tas5805m->i2c = i2c;
tas5805m->pvdd = devm_regulator_get(dev, "pvdd"); tas5805m->pvdd = devm_regulator_get(dev, "pvdd");
if (IS_ERR(tas5805m->pvdd)) { if (IS_ERR(tas5805m->pvdd)) {
dev_err(dev, "failed to get pvdd supply: %ld\n", dev_err(dev, "failed to get pvdd supply: %ld\n",
...@@ -507,6 +552,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) ...@@ -507,6 +552,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
gpiod_set_value(tas5805m->gpio_pdn_n, 1); gpiod_set_value(tas5805m->gpio_pdn_n, 1);
usleep_range(10000, 15000); usleep_range(10000, 15000);
INIT_WORK(&tas5805m->work, do_work);
mutex_init(&tas5805m->lock);
/* Don't register through devm. We need to be able to unregister /* Don't register through devm. We need to be able to unregister
* the component prior to deasserting PDN# * the component prior to deasserting PDN#
*/ */
...@@ -527,6 +575,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c) ...@@ -527,6 +575,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c)
struct device *dev = &i2c->dev; struct device *dev = &i2c->dev;
struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
cancel_work_sync(&tas5805m->work);
snd_soc_unregister_component(dev); snd_soc_unregister_component(dev);
gpiod_set_value(tas5805m->gpio_pdn_n, 0); gpiod_set_value(tas5805m->gpio_pdn_n, 0);
usleep_range(10000, 15000); usleep_range(10000, 15000);
......
...@@ -1141,6 +1141,7 @@ static int fsl_sai_check_version(struct device *dev) ...@@ -1141,6 +1141,7 @@ static int fsl_sai_check_version(struct device *dev)
sai->verid.version = val & sai->verid.version = val &
(FSL_SAI_VERID_MAJOR_MASK | FSL_SAI_VERID_MINOR_MASK); (FSL_SAI_VERID_MAJOR_MASK | FSL_SAI_VERID_MINOR_MASK);
sai->verid.version >>= FSL_SAI_VERID_MINOR_SHIFT;
sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK; sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK;
ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val); ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val);
......
...@@ -1401,13 +1401,17 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, ...@@ -1401,13 +1401,17 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
template.num_kcontrols = le32_to_cpu(w->num_kcontrols); template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL);
if (!kc) if (!kc) {
ret = -ENOMEM;
goto hdr_err; goto hdr_err;
}
kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int),
GFP_KERNEL); GFP_KERNEL);
if (!kcontrol_type) if (!kcontrol_type) {
ret = -ENOMEM;
goto hdr_err; goto hdr_err;
}
for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) {
control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
......
...@@ -318,7 +318,6 @@ static irqreturn_t acp_irq_thread(int irq, void *context) ...@@ -318,7 +318,6 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
{ {
struct snd_sof_dev *sdev = context; struct snd_sof_dev *sdev = context;
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
unsigned int base = desc->dsp_intr_base;
unsigned int val, count = ACP_HW_SEM_RETRY_COUNT; unsigned int val, count = ACP_HW_SEM_RETRY_COUNT;
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat); 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) ...@@ -328,28 +327,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
if (val & ACP_DSP_TO_HOST_IRQ) { /* Wait until acquired HW Semaphore lock or timeout */
while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) { count--;
/* Wait until acquired HW Semaphore lock or timeout */ if (!count) {
count--; dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
if (!count) { return IRQ_NONE;
dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
return IRQ_NONE;
}
} }
sof_ops(sdev)->irq_thread(irq, sdev);
val |= ACP_DSP_TO_HOST_IRQ;
snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val);
/* Unlock or Release HW Semaphore */
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);
return IRQ_HANDLED;
} }
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);
return IRQ_HANDLED;
}; };
static irqreturn_t acp_irq_handler(int irq, void *dev_id) 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) ...@@ -360,8 +351,11 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
unsigned int val; unsigned int val;
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET); val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
if (val) if (val) {
val |= ACP_DSP_TO_HOST_IRQ;
snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val);
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
}
return IRQ_NONE; return IRQ_NONE;
} }
......
...@@ -349,6 +349,9 @@ int ...@@ -349,6 +349,9 @@ int
snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan, snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan,
int param) int param)
{ {
if (param >= ARRAY_SIZE(chan->control))
return -EINVAL;
return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects), return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
port, chan, param, port, chan, param,
chan->control[param], chan->control[param],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment