mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
sound fixes for 7.1-rc6
A collection of recent small fixes and quirks. We still see a bit more changes than wished, but most of them are device-specific ones that are pretty safe to apply, while a core fix is a typical UAF fix for PCM core that was recently caught by fuzzer; so overall nothing looks really worrisome. * Core: - Fix a UAF in PCM OSS proc interface * HD-audio: - Fix memory leaks in CS35L56 driver - Various device-specific quirks for Realtek and CS420x codecs * USB-audio: - Quirk for TAE1160 USB Audio - Fix for Scarlett2 Gen4 direct monitor gain * ASoC: - Fixes for QCom q6asm-dai, Intel bytcht_es8316, and simple-mux codec * FireWire: - Fix for Motu DSP event queue protection -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmoZTLUOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE8RMxAAmdvBYW7xB64onopKCTjdHewCx3nsK9V9jiWi 0xsQDEs1+JukXG4Bag06R2W9EJLrdFewa88QnuwtEG+wMxJO30oJxm/b6k5EkwNu ai8Vd8pFkcxmpAC7cL/ROtQurqW9Tfr+w9qGUTcS12tRuvQV+AjfHvGSlwqiS3K0 ZFPozyPVD6kQ5g3io/GH3HW76ZTLB+jtVx+VYvQsJ43Bii3g2pfNW6HlWQyundPt Q6vLgUHEhvf9fgA76YztQedtoxBxQyuWrZCOV2+qzobW5sJHdOAlh4XmR6VjYzui Gp6Xn4U1wPsP722kqzm+uK6QDVsaGGzKOuwKWYpGBwRYVol0CY/YFC1ZcT19VCMI k6J93OMYZRoAl+ECbbWQjhVN4g8Ut7CQlvcZpPVwr5+HgcoitvuBt41KGUesKFkp 0h8kgy/X59JCJJ+AaZlxKOKoPL+WeVCXm1z9GF3VcS1h9kT1ZXfB1d3nSi9383xR ho+YJYQQiyvXK7ZfESKZgChmC9LBSU5joW77HslXU5tM9ZkLGW1w8O7Zasas7cSm xeNhhR6J3AnfTLX2XHDKWR/w32kqaEYTUr+t1Z997Vm33D7idcOtQIr20AgQon+0 EfKLijHFQB0HCkqgndMXdgjnus9TnXOoJE9aQudRr8rSUgu3dONrPguv+z23y25n 9u7awX4= =IHLg -----END PGP SIGNATURE----- Merge tag 'sound-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "A collection of recent small fixes and quirks. We still see a bit more changes than wished, but most of them are device-specific ones that are pretty safe to apply, while a core fix is a typical UAF fix for PCM core that was recently caught by fuzzer; so overall nothing looks really worrisome. Core: - Fix a UAF in PCM OSS proc interface HD-audio: - Fix memory leaks in CS35L56 driver - Various device-specific quirks for Realtek and CS420x codecs USB-audio: - Quirk for TAE1160 USB Audio - Fix for Scarlett2 Gen4 direct monitor gain ASoC: - Fixes for QCom q6asm-dai, Intel bytcht_es8316, and simple-mux codec FireWire: - Fix for Motu DSP event queue protection" * tag 'sound-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ASoC: codecs: simple-mux: Fix enum control bounds check ALSA: usb-audio: Add iface reset and delay quirk for TAE1160 USB Audio ALSA: hda/cs420x: Add CS4208 fixup for iMac16,1 ALSA: hda/realtek: add quirk for HP Dragonfly Folio G3 2-in-1 ALSA: hda/realtek: Fix speaker output on ASUS ROG Strix G615LP ASoC: qcom: q6asm-dai: use pointer type with kzalloc_obj() ASoC: qcom: q6asm-dai: remove unnecessary braces ASoC: qcom: q6asm-dai: fix error handling in prepare and set_params ASoC: qcom: q6asm-dai: close stream only when running ASoC: qcom: q6asm-dai: do not set stream state in event and trigger callbacks ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors ALSA: hda/realtek: Limit mic boost on Positivo DN140 ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor gain on firmware 2417 ALSA: pcm: oss: Fix setup list UAF on proc write error ALSA: hda: cs35l56: Fix system name string leaks ALSA: hda/realtek: Add HDA_CODEC_QUIRK for Lenovo Yoga Slim 7 14AGP11 ALSA: hda/realtek: Fix incorrect comment for ALC299_FIXUP_PREDATOR_SPK ALSA: firewire-motu: Protect register DSP event queue positions
This commit is contained in:
commit
7b55445960
|
|
@ -2974,8 +2974,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
|
|||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_pcm_str *pstr = entry->private_data;
|
||||
struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
|
||||
struct snd_pcm_oss_setup *setup;
|
||||
|
||||
guard(mutex)(&pstr->oss.setup_mutex);
|
||||
setup = pstr->oss.setup_list;
|
||||
while (setup) {
|
||||
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
|
||||
setup->task_name,
|
||||
|
|
@ -3060,6 +3062,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
|
|||
buffer->error = -ENOMEM;
|
||||
return;
|
||||
}
|
||||
template.task_name = kstrdup(task_name, GFP_KERNEL);
|
||||
if (!template.task_name) {
|
||||
kfree(setup);
|
||||
buffer->error = -ENOMEM;
|
||||
return;
|
||||
}
|
||||
*setup = template;
|
||||
if (pstr->oss.setup_list == NULL)
|
||||
pstr->oss.setup_list = setup;
|
||||
else {
|
||||
|
|
@ -3067,12 +3076,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
|
|||
setup1->next; setup1 = setup1->next);
|
||||
setup1->next = setup;
|
||||
}
|
||||
template.task_name = kstrdup(task_name, GFP_KERNEL);
|
||||
if (! template.task_name) {
|
||||
kfree(setup);
|
||||
buffer->error = -ENOMEM;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*setup = template;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,6 +386,8 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
|
|||
{
|
||||
struct msg_parser *parser = motu->message_parser;
|
||||
|
||||
guard(spinlock_irqsave)(&parser->lock);
|
||||
|
||||
if (parser->pull_pos > parser->push_pos)
|
||||
return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
|
||||
else
|
||||
|
|
@ -395,13 +397,14 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
|
|||
bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
|
||||
{
|
||||
struct msg_parser *parser = motu->message_parser;
|
||||
unsigned int pos = parser->pull_pos;
|
||||
|
||||
if (pos == parser->push_pos)
|
||||
return false;
|
||||
unsigned int pos;
|
||||
|
||||
guard(spinlock_irqsave)(&parser->lock);
|
||||
|
||||
if (parser->pull_pos == parser->push_pos)
|
||||
return false;
|
||||
|
||||
pos = parser->pull_pos;
|
||||
*event = parser->event_queue[pos];
|
||||
|
||||
++pos;
|
||||
|
|
|
|||
|
|
@ -582,6 +582,7 @@ static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
|
||||
SND_PCI_QUIRK(0x106b, 0x7800, "MacPro 6,1", CS4208_MACMINI),
|
||||
SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
|
||||
SND_PCI_QUIRK(0x106b, 0x7f00, "iMac 16,1", CS4208_MBP11),
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5458,7 +5458,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
[ALC299_FIXUP_PREDATOR_SPK] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x21, 0x90170150 }, /* use as headset mic, without its own jack detect */
|
||||
{ 0x21, 0x90170150 }, /* use as internal speaker */
|
||||
{ }
|
||||
}
|
||||
},
|
||||
|
|
@ -7070,6 +7070,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
|
||||
SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
|
|
@ -7324,6 +7325,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
HDA_CODEC_QUIRK(0x1043, 0x1204, "ASUS Strix G16 G615JMR", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
|
||||
HDA_CODEC_QUIRK(0x1043, 0x1214, "ASUS ROG Strix G615LP", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
|
|
@ -7778,6 +7780,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TXNW2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3929, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x392b, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x394c, "Lenovo Yoga Slim 7 14AGP11", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||
|
|
@ -7845,6 +7848,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
|
||||
SND_PCI_QUIRK(0x1e50, 0x7007, "Positivo DN50E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1e50, 0x7038, "Positivo DN140", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1ee7, 0x2081, "HONOR MRB-XXX M1020", ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO),
|
||||
SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC),
|
||||
|
|
|
|||
|
|
@ -1025,7 +1025,7 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
|
|||
u32 values[HDA_MAX_COMPONENTS];
|
||||
char hid_string[8];
|
||||
struct acpi_device *adev;
|
||||
const char *property, *sub;
|
||||
const char *property;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
|
|
@ -1047,7 +1047,8 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
|
|||
/* Initialize things that could be overwritten by a fixup */
|
||||
cs35l56->index = -1;
|
||||
|
||||
sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
|
||||
const char *sub __free(kfree) = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
|
||||
|
||||
ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1095,15 +1096,16 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
|
|||
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index,
|
||||
cs35l56->num_amps, -1);
|
||||
if (ret == -ENOENT) {
|
||||
cs35l56->system_name = sub;
|
||||
cs35l56->system_name = devm_kstrdup(cs35l56->base.dev, sub, GFP_KERNEL);
|
||||
} else if (ret >= 0) {
|
||||
cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
|
||||
kfree(sub);
|
||||
if (!cs35l56->system_name)
|
||||
return -ENOMEM;
|
||||
cs35l56->system_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL,
|
||||
"%s-spkid%d", sub, ret);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!cs35l56->system_name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
|
||||
|
|
@ -1254,7 +1256,6 @@ void cs35l56_hda_remove(struct device *dev)
|
|||
|
||||
cs_dsp_remove(&cs35l56->cs_dsp);
|
||||
|
||||
kfree(cs35l56->system_name);
|
||||
pm_runtime_put_noidle(cs35l56->base.dev);
|
||||
|
||||
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
|
||||
struct simple_mux *priv = snd_soc_component_get_drvdata(c);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > e->items)
|
||||
if (ucontrol->value.enumerated.item[0] >= e->items)
|
||||
return -EINVAL;
|
||||
|
||||
if (priv->mux == ucontrol->value.enumerated.item[0])
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
|
|||
struct gpio_desc *speaker_en_gpio;
|
||||
struct device *codec_dev;
|
||||
bool speaker_en;
|
||||
bool mclk_enabled;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
|
||||
{
|
||||
if (!priv->mclk_enabled)
|
||||
return;
|
||||
|
||||
clk_disable_unprepare(priv->mclk);
|
||||
priv->mclk_enabled = false;
|
||||
}
|
||||
|
||||
static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
|
||||
|
|
@ -227,12 +237,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
|
|||
ret = clk_prepare_enable(priv->mclk);
|
||||
if (ret)
|
||||
dev_err(card->dev, "unable to enable MCLK\n");
|
||||
else
|
||||
priv->mclk_enabled = true;
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
|
||||
SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "can't set codec clock %d\n", ret);
|
||||
return ret;
|
||||
goto err_disable_mclk;
|
||||
}
|
||||
|
||||
ret = snd_soc_card_jack_new_pins(card, "Headset",
|
||||
|
|
@ -241,13 +253,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
|
|||
ARRAY_SIZE(byt_cht_es8316_jack_pins));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "jack creation failed %d\n", ret);
|
||||
return ret;
|
||||
goto err_disable_mclk;
|
||||
}
|
||||
|
||||
snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
|
||||
snd_soc_component_set_jack(codec, &priv->jack, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_mclk:
|
||||
byt_cht_es8316_disable_mclk(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
|
||||
{
|
||||
struct snd_soc_card *card = runtime->card;
|
||||
struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
|
||||
|
||||
byt_cht_es8316_disable_mclk(priv);
|
||||
}
|
||||
|
||||
static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
|
|
@ -353,6 +377,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
|
|||
| SND_SOC_DAIFMT_CBC_CFC,
|
||||
.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
|
||||
.init = byt_cht_es8316_init,
|
||||
.exit = byt_cht_es8316_exit,
|
||||
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -186,12 +186,10 @@ static void event_handler(uint32_t opcode, uint32_t token,
|
|||
case ASM_CLIENT_EVENT_CMD_RUN_DONE:
|
||||
break;
|
||||
case ASM_CLIENT_EVENT_CMD_EOS_DONE:
|
||||
prtd->state = Q6ASM_STREAM_STOPPED;
|
||||
break;
|
||||
case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
|
||||
case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
|
||||
snd_pcm_period_elapsed(substream);
|
||||
break;
|
||||
}
|
||||
case ASM_CLIENT_EVENT_DATA_READ_DONE:
|
||||
snd_pcm_period_elapsed(substream);
|
||||
if (prtd->state == Q6ASM_STREAM_RUNNING)
|
||||
|
|
@ -227,9 +225,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
|
|||
/* rate and channels are sent to audio driver */
|
||||
if (prtd->state == Q6ASM_STREAM_RUNNING) {
|
||||
/* clear the previous setup if any */
|
||||
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
|
||||
q6asm_unmap_memory_regions(substream->stream,
|
||||
prtd->audio_client);
|
||||
ret = q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to close q6asm stream %d\n", prtd->stream_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to unmap memory regions for q6asm stream %d\n",
|
||||
prtd->stream_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
q6routing_stream_close(soc_prtd->dai_link->id,
|
||||
substream->stream);
|
||||
prtd->state = Q6ASM_STREAM_STOPPED;
|
||||
|
|
@ -297,8 +305,6 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
|
|||
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
|
||||
open_err:
|
||||
q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -341,7 +347,6 @@ static int q6asm_dai_trigger(struct snd_soc_component *component,
|
|||
0, 0, 0);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
prtd->state = Q6ASM_STREAM_STOPPED;
|
||||
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
|
||||
CMD_EOS);
|
||||
break;
|
||||
|
|
@ -378,7 +383,7 @@ static int q6asm_dai_open(struct snd_soc_component *component,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
prtd = kzalloc_obj(struct q6asm_dai_rtd);
|
||||
prtd = kzalloc_obj(*prtd);
|
||||
if (prtd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -457,12 +462,12 @@ static int q6asm_dai_close(struct snd_soc_component *component,
|
|||
struct q6asm_dai_rtd *prtd = runtime->private_data;
|
||||
|
||||
if (prtd->audio_client) {
|
||||
if (prtd->state)
|
||||
if (prtd->state == Q6ASM_STREAM_RUNNING) {
|
||||
q6asm_cmd(prtd->audio_client, prtd->stream_id,
|
||||
CMD_CLOSE);
|
||||
|
||||
q6asm_unmap_memory_regions(substream->stream,
|
||||
q6asm_unmap_memory_regions(substream->stream,
|
||||
prtd->audio_client);
|
||||
}
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
}
|
||||
|
|
@ -555,8 +560,6 @@ static void compress_event_handler(uint32_t opcode, uint32_t token,
|
|||
snd_compr_drain_notify(prtd->cstream);
|
||||
prtd->notify_on_drain = false;
|
||||
|
||||
} else {
|
||||
prtd->state = Q6ASM_STREAM_STOPPED;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -674,7 +677,7 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
|
|||
struct snd_soc_pcm_runtime *rtd = stream->private_data;
|
||||
|
||||
if (prtd->audio_client) {
|
||||
if (prtd->state) {
|
||||
if (prtd->state == Q6ASM_STREAM_RUNNING) {
|
||||
q6asm_cmd(prtd->audio_client, prtd->stream_id,
|
||||
CMD_CLOSE);
|
||||
if (prtd->next_track_stream_id) {
|
||||
|
|
@ -682,11 +685,11 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
|
|||
prtd->next_track_stream_id,
|
||||
CMD_CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
snd_dma_free_pages(&prtd->dma_buffer);
|
||||
q6asm_unmap_memory_regions(stream->direction,
|
||||
q6asm_unmap_memory_regions(stream->direction,
|
||||
prtd->audio_client);
|
||||
}
|
||||
snd_dma_free_pages(&prtd->dma_buffer);
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
}
|
||||
|
|
@ -916,7 +919,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
|
|||
prtd->session_id, dir);
|
||||
if (ret) {
|
||||
dev_err(dev, "Stream reg failed ret:%d\n", ret);
|
||||
goto q6_err;
|
||||
goto routing_err;
|
||||
}
|
||||
|
||||
ret = __q6asm_dai_compr_set_codec_params(component, stream,
|
||||
|
|
@ -942,11 +945,11 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
|
|||
return 0;
|
||||
|
||||
q6_err:
|
||||
q6routing_stream_close(rtd->dai_link->id, dir);
|
||||
routing_err:
|
||||
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
|
||||
|
||||
open_err:
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1014,7 +1017,6 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
|
|||
0, 0, 0);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
prtd->state = Q6ASM_STREAM_STOPPED;
|
||||
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
|
||||
CMD_EOS);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2504,6 +2504,27 @@ static int scarlett2_has_config_item(
|
|||
return !!private->config_set->items[config_item_num].offset;
|
||||
}
|
||||
|
||||
/* Return the configuration item's offset, applying any per-firmware
|
||||
* overrides.
|
||||
*
|
||||
* Firmware 2417 for the 2i2 Gen 4 moved DIRECT_MONITOR_GAIN by 4
|
||||
* bytes. Apply that shift here so that the rest of the driver can
|
||||
* keep using the single config set. This override can be removed
|
||||
* once the multi-config-set framework lands.
|
||||
*/
|
||||
static int scarlett2_config_item_offset(
|
||||
struct scarlett2_data *private, int config_item_num)
|
||||
{
|
||||
int offset = private->config_set->items[config_item_num].offset;
|
||||
|
||||
if (config_item_num == SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN &&
|
||||
private->info == &s2i2_gen4_info &&
|
||||
private->firmware_version >= 2417)
|
||||
offset = 0x2a4;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Send a USB message to get configuration parameters; result placed in *buf */
|
||||
static int scarlett2_usb_get_config(
|
||||
struct usb_mixer_interface *mixer,
|
||||
|
|
@ -2513,6 +2534,7 @@ static int scarlett2_usb_get_config(
|
|||
const struct scarlett2_config *config_item =
|
||||
&private->config_set->items[config_item_num];
|
||||
int size, err, i;
|
||||
int item_offset;
|
||||
u8 *buf_8;
|
||||
u8 value;
|
||||
|
||||
|
|
@ -2522,13 +2544,15 @@ static int scarlett2_usb_get_config(
|
|||
if (!config_item->offset)
|
||||
return -EFAULT;
|
||||
|
||||
item_offset = scarlett2_config_item_offset(private, config_item_num);
|
||||
|
||||
/* Writes to the parameter buffer are always 1 byte */
|
||||
size = config_item->size ? config_item->size : 8;
|
||||
|
||||
/* For byte-sized parameters, retrieve directly into buf */
|
||||
if (size >= 8) {
|
||||
size = size / 8 * count;
|
||||
err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
|
||||
err = scarlett2_usb_get(mixer, item_offset, buf, size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (config_item->size == 16) {
|
||||
|
|
@ -2546,7 +2570,7 @@ static int scarlett2_usb_get_config(
|
|||
}
|
||||
|
||||
/* For bit-sized parameters, retrieve into value */
|
||||
err = scarlett2_usb_get(mixer, config_item->offset, &value, 1);
|
||||
err = scarlett2_usb_get(mixer, item_offset, &value, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
@ -2696,7 +2720,8 @@ static int scarlett2_usb_set_config(
|
|||
*/
|
||||
if (config_item->size >= 8) {
|
||||
size = config_item->size / 8;
|
||||
offset = config_item->offset + index * size;
|
||||
offset = scarlett2_config_item_offset(private, config_item_num) +
|
||||
index * size;
|
||||
|
||||
/* If updating a bit, retrieve the old value, set/clear the
|
||||
* bit as needed, and update value
|
||||
|
|
@ -2705,7 +2730,7 @@ static int scarlett2_usb_set_config(
|
|||
u8 tmp;
|
||||
|
||||
size = 1;
|
||||
offset = config_item->offset;
|
||||
offset = scarlett2_config_item_offset(private, config_item_num);
|
||||
|
||||
err = scarlett2_usb_get(mixer, offset, &tmp, 1);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -2449,6 +2449,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
|||
QUIRK_FLAG_DSD_RAW),
|
||||
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
|
||||
QUIRK_FLAG_SET_IFACE_FIRST),
|
||||
DEVICE_FLG(0x25aa, 0x600b, /* TAE1159 */
|
||||
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
|
||||
DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */
|
||||
QUIRK_FLAG_DSD_RAW),
|
||||
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user