mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
sound fixes for 7.1-rc1
Here are the rest of small updates for 7.1-rc1. All small fixes
mostly for device-specific issues or regressions.
* Core:
- Fix a potential data race in fasync handling
* USB-audio:
- New device support: Line6 POD HD PRO, NexiGo N930W webcam
- Fixes for Audio Advantage Micro II SPDIF switch and E-MU sample rates
- Limit UAC2 rate parsing to prevent potential overflows
* HD-Audio:
- Device-specific quirks for HP, Acer, and Honor laptops
- Fix for TAS2781 SPI device abnormal sound
- Move Intel firmware loading into probe work to avoid stalling
* ASoC:
- New support for TI TAS5832
- Fixes for SoundWire SDCA/DisCo boolean parsing
- Driver-specific fixes for Intel SOF, ES8311, RT1320, and PXA2xx
* Misc:
- Fixes for resource leaks and data races in 6fire, caiaq, als4000,
and pcmtest drivers
-----BEGIN PGP SIGNATURE-----
iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmnqD8QOHHRpd2FpQHN1
c2UuZGUACgkQLtJE4w1nLE+rBA//fmPM0+DdrIGvI/62mQmpCeUcOt4Ijtu53/lw
AL1P7aex+45Mt7QfvrwJdMhXb5EZ+Pm7Fh8/+gf3gaC8Z9oRmFzkhAZMe+ne20Uu
CekPqDVJ55AO5enVGV2L7Lz9Hy8BQ3QqYBVh/7n25k44pYdYmfj/YNUKi8PoaQiS
ddijA4mrhPOUIIR8QWp950R6mU4sesVROC+ni+b3HqMXNOHo4+iKvTI4gvHN3JLJ
HfmLiqTgo04tmDTUJWSTW5n9PmW7+8tzawTH6+30fA7RAHGa+rjxAI+eGRvAyCmi
Eyzqsnp9l95fiGXozZJonOjPycrWge7uxEILO3eyLyS1YjgZ1JL97ykImEzOvn2F
i6GlnjQUdOcWujcvZLjIDHy/kVPKdNBTTLtNh/sm/Up8zuLRRV/miWK/jBRd06cr
f2Om/YzOVIbwYZEealiJyQjRxuNJ+x+cmCMruUmyENJsVu3Uz+7pR53rVGvqTduh
ISz+U5m5jg6yxwEx7lamMbavkg5CCIc+phGQRBfs5SrKKn3Wo/vgEU1GH0peQq4X
k4cr4nkMHUOCtMiMsyaaTet3pAMEFIx07zArutx05YAjMA9nVp4jsA7deEbYcZhf
PdXCMFHeODQBDWevTdyiE1KbyBMRzFuuzAXgXaylsX1cXl5iGYzdzIzJc03g1VjT
hEqcqRs=
=0UEp
-----END PGP SIGNATURE-----
Merge tag 'sound-fix-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Here are the rest of small updates for 7.1-rc1. All small fixes mostly
for device-specific issues or regressions.
Core:
- Fix a potential data race in fasync handling
USB-audio:
- New device support: Line6 POD HD PRO, NexiGo N930W webcam
- Fixes for Audio Advantage Micro II SPDIF switch and E-MU sample
rates
- Limit UAC2 rate parsing to prevent potential overflows
HD-Audio:
- Device-specific quirks for HP, Acer, and Honor laptops
- Fix for TAS2781 SPI device abnormal sound
- Move Intel firmware loading into probe work to avoid stalling
ASoC:
- New support for TI TAS5832
- Fixes for SoundWire SDCA/DisCo boolean parsing
- Driver-specific fixes for Intel SOF, ES8311, RT1320, and PXA2xx
Misc:
- Fixes for resource leaks and data races in 6fire, caiaq, als4000,
and pcmtest drivers"
* tag 'sound-fix-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (41 commits)
Revert "ALSA: pcmtest: fix reference leak on failed device registration"
ASoC: tas2781: Add tas5832 support
ASoC: dt-bindings: ti,tas2781: Add TAS5832 support
ALSA: usb-audio: Fix Audio Advantage Micro II SPDIF switch
ALSA: usb-audio: Avoid false E-MU sample-rate notifications
ASoC: sdw_utils: cs42l43: allow spk component names to be combined
ASoC: qcom: x1e80100: limit speaker volumes
ALSA: hda/realtek - Add mute LED support for HP Victus 15-fa2xxx
ALSA: pcmtest: Fix resource leaks in module init error paths
ALSA: usb-audio/line6: Add support for POD HD PRO
ALSA: hda/realtek: Add LED fixup for HP EliteBook 6 G2a Laptops
ASoC: SDCA: Fix reading of mipi-sdca-control-deferrable
regmap: sdw-mbq: Allow defers on undeferrable controls
Revert "ALSA: usb-audio: Add quirk for SmartlinkTechnology M01"
ALSA: als4000: Fix capture trigger chip->mode race
ALSA: core: Fix potential data race at fasync handling
ALSA: hda/tas2781: Fix sound abnormal issue on some SPI device
ALSA: hda/realtek: add quirk for Acer Nitro 16 AN16-41
ALSA: caiaq: Fix control_put() result and cache rollback
ALSA: pcmtest: fix reference leak on failed device registration
...
This commit is contained in:
commit
1fe93b2a2a
|
|
@ -1,5 +1,5 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2022 - 2025 Texas Instruments Incorporated
|
||||
# Copyright (C) 2022 - 2026 Texas Instruments Incorporated
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ti,tas2781.yaml#
|
||||
|
|
@ -107,6 +107,9 @@ properties:
|
|||
|
||||
ti,tas5830: 65-W Stereo, Digital Input, High Efficiency Closed-Loop
|
||||
Class-D Amplifier with Class-H Algorithm
|
||||
|
||||
ti,tas5832: 81-W Stereo, Digital Input, High Efficiency Closed-Loop
|
||||
Class-D Amplifier with Class-H Algorithm
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
|
|
@ -128,6 +131,7 @@ properties:
|
|||
- ti,tas5827
|
||||
- ti,tas5828
|
||||
- ti,tas5830
|
||||
- ti,tas5832
|
||||
- const: ti,tas2781
|
||||
- enum:
|
||||
- ti,tas2781
|
||||
|
|
@ -264,6 +268,7 @@ allOf:
|
|||
- ti,tas5827
|
||||
- ti,tas5828
|
||||
- ti,tas5830
|
||||
- ti,tas5832
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg,
|
|||
|
||||
static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
|
||||
unsigned int reg, unsigned int val,
|
||||
int mbq_size, bool deferrable)
|
||||
int mbq_size)
|
||||
{
|
||||
int shift = mbq_size * BITS_PER_BYTE;
|
||||
int ret;
|
||||
|
|
@ -88,17 +88,14 @@ static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = sdw_write_no_pm(slave, reg, val & 0xff);
|
||||
if (deferrable && ret == -ENODATA)
|
||||
return -EAGAIN;
|
||||
|
||||
return ret;
|
||||
return sdw_write_no_pm(slave, reg, val & 0xff);
|
||||
}
|
||||
|
||||
static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct regmap_mbq_context *ctx = context;
|
||||
struct sdw_slave *slave = ctx->sdw;
|
||||
struct device *dev = ctx->dev;
|
||||
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
|
||||
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
|
||||
int ret;
|
||||
|
|
@ -113,13 +110,16 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va
|
|||
* process a single wait/timeout on function busy and a single retry
|
||||
* of the transaction.
|
||||
*/
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable);
|
||||
if (ret == -EAGAIN) {
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
|
||||
if (ret == -ENODATA) {
|
||||
if (!deferrable)
|
||||
dev_warn(dev, "Defer on undeferrable control: %x\n", reg);
|
||||
|
||||
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false);
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -127,18 +127,14 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va
|
|||
|
||||
static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave,
|
||||
unsigned int reg, unsigned int *val,
|
||||
int mbq_size, bool deferrable)
|
||||
int mbq_size)
|
||||
{
|
||||
int shift = BITS_PER_BYTE;
|
||||
int read;
|
||||
|
||||
read = sdw_read_no_pm(slave, reg);
|
||||
if (read < 0) {
|
||||
if (deferrable && read == -ENODATA)
|
||||
return -EAGAIN;
|
||||
|
||||
if (read < 0)
|
||||
return read;
|
||||
}
|
||||
|
||||
*val = read;
|
||||
|
||||
|
|
@ -158,6 +154,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
|
|||
{
|
||||
struct regmap_mbq_context *ctx = context;
|
||||
struct sdw_slave *slave = ctx->sdw;
|
||||
struct device *dev = ctx->dev;
|
||||
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
|
||||
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
|
||||
int ret;
|
||||
|
|
@ -172,13 +169,16 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
|
|||
* process a single wait/timeout on function busy and a single retry
|
||||
* of the transaction.
|
||||
*/
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable);
|
||||
if (ret == -EAGAIN) {
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
|
||||
if (ret == -ENODATA) {
|
||||
if (!deferrable)
|
||||
dev_warn(dev, "Defer on undeferable control: %x\n", reg);
|
||||
|
||||
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false);
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ enum audio_device {
|
|||
TAS5827,
|
||||
TAS5828,
|
||||
TAS5830,
|
||||
TAS5832,
|
||||
TAS_OTHERS,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -331,12 +331,15 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
|
|||
if (dev->dev.of_node) {
|
||||
/* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */
|
||||
rst_gpio = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH);
|
||||
ret = PTR_ERR(rst_gpio);
|
||||
if (ret == -ENOENT)
|
||||
reset_gpio = -1;
|
||||
else if (ret)
|
||||
return ret;
|
||||
reset_gpio = desc_to_gpio(rst_gpio);
|
||||
if (IS_ERR(rst_gpio)) {
|
||||
ret = PTR_ERR(rst_gpio);
|
||||
if (ret == -ENOENT)
|
||||
reset_gpio = -1;
|
||||
else if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
reset_gpio = desc_to_gpio(rst_gpio);
|
||||
}
|
||||
} else {
|
||||
if (cpu_is_pxa27x())
|
||||
reset_gpio = 113;
|
||||
|
|
|
|||
|
|
@ -100,14 +100,18 @@ static LIST_HEAD(snd_fasync_list);
|
|||
static void snd_fasync_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct snd_fasync *fasync;
|
||||
int signal, poll;
|
||||
|
||||
spin_lock_irq(&snd_fasync_lock);
|
||||
while (!list_empty(&snd_fasync_list)) {
|
||||
fasync = list_first_entry(&snd_fasync_list, struct snd_fasync, list);
|
||||
list_del_init(&fasync->list);
|
||||
if (!fasync->on)
|
||||
continue;
|
||||
signal = fasync->signal;
|
||||
poll = fasync->poll;
|
||||
spin_unlock_irq(&snd_fasync_lock);
|
||||
if (fasync->on)
|
||||
kill_fasync(&fasync->fasync, fasync->signal, fasync->poll);
|
||||
kill_fasync(&fasync->fasync, signal, poll);
|
||||
spin_lock_irq(&snd_fasync_lock);
|
||||
}
|
||||
spin_unlock_irq(&snd_fasync_lock);
|
||||
|
|
@ -158,7 +162,10 @@ void snd_fasync_free(struct snd_fasync *fasync)
|
|||
{
|
||||
if (!fasync)
|
||||
return;
|
||||
fasync->on = 0;
|
||||
|
||||
scoped_guard(spinlock_irq, &snd_fasync_lock)
|
||||
list_del_init(&fasync->list);
|
||||
|
||||
flush_work(&snd_fasync_work);
|
||||
kfree(fasync);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -754,13 +754,22 @@ static int __init mod_init(void)
|
|||
|
||||
err = init_debug_files(buf_allocated);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_free_patterns;
|
||||
err = platform_device_register(&pcmtst_pdev);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_clear_debug;
|
||||
err = platform_driver_register(&pcmtst_pdrv);
|
||||
if (err)
|
||||
if (err) {
|
||||
platform_device_unregister(&pcmtst_pdev);
|
||||
goto err_clear_debug;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clear_debug:
|
||||
clear_debug_files();
|
||||
err_free_patterns:
|
||||
free_pattern_buffers();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ struct vx_cmd_info {
|
|||
void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd);
|
||||
|
||||
/**
|
||||
* vx_send_pipe_cmd_params - fill first command word for pipe commands
|
||||
* vx_set_pipe_cmd_params - fill first command word for pipe commands
|
||||
* @rmh: the rmh to be modified
|
||||
* @is_capture: 0 = playback, 1 = capture operation
|
||||
* @param1: first pipe-parameter
|
||||
|
|
|
|||
|
|
@ -4111,6 +4111,7 @@ enum {
|
|||
ALC245_FIXUP_ACER_MICMUTE_LED,
|
||||
ALC245_FIXUP_CS35L41_I2C_2_MUTE_LED,
|
||||
ALC236_FIXUP_HP_DMIC,
|
||||
ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO,
|
||||
};
|
||||
|
||||
/* A special fixup for Lenovo C940 and Yoga Duet 7;
|
||||
|
|
@ -6653,6 +6654,16 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
{ 0x12, 0x90a60160 }, /* use as internal mic */
|
||||
{ }
|
||||
},
|
||||
},
|
||||
[ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x14, 0x90170111 },
|
||||
{ 0x19, 0x03a1113c },
|
||||
{ 0x1a, 0x22a190a0 },
|
||||
{ 0x1b, 0x90170110 },
|
||||
{ }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -6706,6 +6717,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
|
||||
SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED),
|
||||
SND_PCI_QUIRK(0x1025, 0x173a, "Acer Swift SFG14-73", ALC245_FIXUP_ACER_MICMUTE_LED),
|
||||
|
|
@ -7142,6 +7154,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8d90, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dcd, "HP Victus 15-fa2xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9b, "HP 17 Turbine OmniBook 7 UMA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9c, "HP 17 Turbine OmniBook 7 DIS", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8d9d, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
|
@ -7214,6 +7227,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8f0e, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f2d, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f2e, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f3c, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f3d, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f40, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f41, "HP ZBook 8 G2a 16", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f42, "HP ZBook 8 G2a 14W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
|
|
@ -7751,6 +7766,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(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),
|
||||
SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
|
|
@ -7971,6 +7987,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
|
|||
{.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"},
|
||||
{.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
|
||||
{.id = ALC245_FIXUP_BASS_HP_DAC, .name = "alc245-fixup-bass-hp-dac"},
|
||||
{.id = ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO, .name = "alc256-honor-mrb-xxx-m1020-audio"},
|
||||
{}
|
||||
};
|
||||
#define ALC225_STANDARD_PINS \
|
||||
|
|
|
|||
|
|
@ -788,6 +788,7 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
|
|||
}
|
||||
if (strstr(dev_name(&spi->dev), "TXNW2781")) {
|
||||
device_name = "TXNW2781";
|
||||
tas_hda->priv->chip_id = TAS2781;
|
||||
} else {
|
||||
dev_err(tas_priv->dev, "Unmatched spi dev %s\n",
|
||||
dev_name(&spi->dev));
|
||||
|
|
|
|||
|
|
@ -127,10 +127,6 @@ struct azx {
|
|||
unsigned int beep_mode;
|
||||
bool ctl_dev_id;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
const struct firmware *fw;
|
||||
#endif
|
||||
|
||||
/* flags */
|
||||
int bdl_pos_adj;
|
||||
unsigned int running:1;
|
||||
|
|
|
|||
|
|
@ -1385,9 +1385,6 @@ static void azx_free(struct azx *chip)
|
|||
azx_free_streams(chip);
|
||||
snd_hdac_bus_exit(bus);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
release_firmware(chip->fw);
|
||||
#endif
|
||||
display_power(chip, false);
|
||||
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
|
||||
|
|
@ -2037,24 +2034,6 @@ static int azx_first_init(struct azx *chip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
/* callback from request_firmware_nowait() */
|
||||
static void azx_firmware_cb(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct snd_card *card = context;
|
||||
struct azx *chip = card->private_data;
|
||||
|
||||
if (fw)
|
||||
chip->fw = fw;
|
||||
else
|
||||
dev_err(card->dev, "Cannot load firmware, continue without patching\n");
|
||||
if (!chip->disabled) {
|
||||
/* continue probing */
|
||||
azx_probe_continue(chip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int disable_msi_reset_irq(struct azx *chip)
|
||||
{
|
||||
struct hdac_bus *bus = azx_bus(chip);
|
||||
|
|
@ -2131,7 +2110,6 @@ static int azx_probe(struct pci_dev *pci,
|
|||
struct snd_card *card;
|
||||
struct hda_intel *hda;
|
||||
struct azx *chip;
|
||||
bool schedule_probe;
|
||||
int dev;
|
||||
int err;
|
||||
|
||||
|
|
@ -2227,22 +2205,7 @@ static int azx_probe(struct pci_dev *pci,
|
|||
chip->disabled = true;
|
||||
}
|
||||
|
||||
schedule_probe = !chip->disabled;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (patch[dev] && *patch[dev]) {
|
||||
dev_info(card->dev, "Applying patch firmware '%s'\n",
|
||||
patch[dev]);
|
||||
err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
|
||||
&pci->dev, GFP_KERNEL, card,
|
||||
azx_firmware_cb);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
schedule_probe = false; /* continued in azx_firmware_cb() */
|
||||
}
|
||||
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
|
||||
|
||||
if (schedule_probe)
|
||||
if (!chip->disabled)
|
||||
schedule_delayed_work(&hda->probe_work, 0);
|
||||
|
||||
set_bit(dev, probed_devs);
|
||||
|
|
@ -2371,11 +2334,20 @@ static int azx_probe_continue(struct azx *chip)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (chip->fw) {
|
||||
err = snd_hda_load_patch(&chip->bus, chip->fw->size,
|
||||
chip->fw->data);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
if (patch[dev] && *patch[dev]) {
|
||||
const struct firmware *fw = NULL;
|
||||
|
||||
dev_info(&pci->dev, "Applying patch firmware '%s'\n",
|
||||
patch[dev]);
|
||||
if (request_firmware(&fw, patch[dev], &pci->dev) < 0) {
|
||||
dev_err(&pci->dev,
|
||||
"Cannot load firmware, continue without patching\n");
|
||||
} else {
|
||||
err = snd_hda_load_patch(&chip->bus, fw->size, fw->data);
|
||||
release_firmware(fw);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -421,30 +421,26 @@ static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int
|
|||
{
|
||||
struct snd_sb *chip = snd_pcm_substream_chip(substream);
|
||||
int result = 0;
|
||||
|
||||
/* FIXME race condition in here!!!
|
||||
chip->mode non-atomic update gets consistently protected
|
||||
by reg_lock always, _except_ for this place!!
|
||||
Probably need to take reg_lock as outer (or inner??) lock, too.
|
||||
(or serialize both lock operations? probably not, though... - racy?)
|
||||
*/
|
||||
guard(spinlock)(&chip->mixer_lock);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
chip->mode |= SB_RATE_LOCK_CAPTURE;
|
||||
snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL,
|
||||
capture_cmd(chip));
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
chip->mode &= ~SB_RATE_LOCK_CAPTURE;
|
||||
snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL,
|
||||
capture_cmd(chip));
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
break;
|
||||
|
||||
guard(spinlock)(&chip->reg_lock);
|
||||
scoped_guard(spinlock, &chip->mixer_lock) {
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
chip->mode |= SB_RATE_LOCK_CAPTURE;
|
||||
snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL,
|
||||
capture_cmd(chip));
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
chip->mode &= ~SB_RATE_LOCK_CAPTURE;
|
||||
snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL,
|
||||
capture_cmd(chip));
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -761,6 +761,7 @@ static int es8311_set_bias_level(struct snd_soc_component *component,
|
|||
{
|
||||
struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
|
|
@ -769,17 +770,21 @@ static int es8311_set_bias_level(struct snd_soc_component *component,
|
|||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
|
||||
int ret = clk_prepare_enable(es8311->mclk);
|
||||
ret = clk_prepare_enable(es8311->mclk);
|
||||
if (ret) {
|
||||
dev_err(component->dev,
|
||||
"unable to prepare mclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_component_update_bits(
|
||||
component, ES8311_SYS3,
|
||||
ES8311_SYS3_PDN_VMIDSEL_MASK,
|
||||
ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED);
|
||||
ret = snd_soc_component_update_bits(
|
||||
component, ES8311_SYS3,
|
||||
ES8311_SYS3_PDN_VMIDSEL_MASK,
|
||||
ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED);
|
||||
if (ret < 0) {
|
||||
clk_disable_unprepare(es8311->mclk);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -862,13 +867,18 @@ static int es8311_suspend(struct snd_soc_component *component)
|
|||
static int es8311_resume(struct snd_soc_component *component)
|
||||
{
|
||||
struct es8311_priv *es8311;
|
||||
int ret;
|
||||
|
||||
es8311 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
es8311_reset(component, false);
|
||||
|
||||
regcache_cache_only(es8311->regmap, false);
|
||||
regcache_sync(es8311->regmap);
|
||||
ret = regcache_sync(es8311->regmap);
|
||||
if (ret) {
|
||||
dev_err(component->dev, "unable to sync regcache\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1498,6 +1498,7 @@ static int rt1320_rae_load(struct rt1320_sdw_priv *rt1320)
|
|||
}
|
||||
if (!retry && !(value & 0x40)) {
|
||||
dev_err(dev, "%s: RAE is not ready to load\n", __func__);
|
||||
release_firmware(rae_fw);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2487,7 +2487,7 @@ static int tas2781_cali_preproc(struct tasdevice_priv *priv, int i)
|
|||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
priv->tasdevice[i].cali_specific = spec;
|
||||
rc = tasdevice_dev_bulk_read(priv, i, p->r0_reg, r0_deflt, 4);
|
||||
rc = priv->dev_bulk_read(priv, i, p->r0_reg, r0_deflt, 4);
|
||||
if (rc < 0) {
|
||||
dev_err(priv->dev, "invalid RE from %d = %d\n", i, rc);
|
||||
return rc;
|
||||
|
|
@ -2511,9 +2511,8 @@ static int tas2781_cali_preproc(struct tasdevice_priv *priv, int i)
|
|||
TASDEVICE_REG(0, 0x1b, 0x34) :
|
||||
TASDEVICE_REG(0, 0x18, 0x1c);
|
||||
|
||||
rc = tasdevice_dev_bulk_read(priv, i,
|
||||
spec->sin_gni_reg,
|
||||
spec->sin_gni, 4);
|
||||
rc = priv->dev_bulk_read(priv, i, spec->sin_gni_reg,
|
||||
spec->sin_gni, 4);
|
||||
if (rc < 0) {
|
||||
dev_err(priv->dev, "wrong sinegaini %d = %d\n",
|
||||
i, rc);
|
||||
|
|
|
|||
|
|
@ -119,10 +119,10 @@ static const struct i2c_device_id tasdevice_id[] = {
|
|||
{ "tas5827", TAS5827 },
|
||||
{ "tas5828", TAS5828 },
|
||||
{ "tas5830", TAS5830 },
|
||||
{ "tas5832", TAS5832 },
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id tasdevice_of_match[] = {
|
||||
{ .compatible = "ti,tas2020", .data = &tasdevice_id[TAS2020] },
|
||||
{ .compatible = "ti,tas2118", .data = &tasdevice_id[TAS2118] },
|
||||
|
|
@ -143,10 +143,10 @@ static const struct of_device_id tasdevice_of_match[] = {
|
|||
{ .compatible = "ti,tas5827", .data = &tasdevice_id[TAS5827] },
|
||||
{ .compatible = "ti,tas5828", .data = &tasdevice_id[TAS5828] },
|
||||
{ .compatible = "ti,tas5830", .data = &tasdevice_id[TAS5830] },
|
||||
{ .compatible = "ti,tas5832", .data = &tasdevice_id[TAS5832] },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tasdevice_of_match);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tas2781_digital_getvol - get the volum control
|
||||
|
|
@ -1746,6 +1746,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
|
|||
case TAS5827:
|
||||
case TAS5828:
|
||||
case TAS5830:
|
||||
case TAS5832:
|
||||
/* If DSP FW fail, DSP kcontrol won't be created. */
|
||||
tasdevice_dsp_remove(tas_priv);
|
||||
}
|
||||
|
|
@ -1917,6 +1918,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec)
|
|||
case TAS5827:
|
||||
case TAS5828:
|
||||
case TAS5830:
|
||||
case TAS5832:
|
||||
p = (struct snd_kcontrol_new *)tas5825_snd_controls;
|
||||
size = ARRAY_SIZE(tas5825_snd_controls);
|
||||
break;
|
||||
|
|
@ -2083,7 +2085,6 @@ static void tasdevice_i2c_remove(struct i2c_client *client)
|
|||
tasdevice_remove(tas_priv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id tasdevice_acpi_match[] = {
|
||||
{ "TXNW2020", (kernel_ulong_t)&tasdevice_id[TAS2020] },
|
||||
{ "TXNW2118", (kernel_ulong_t)&tasdevice_id[TAS2118] },
|
||||
|
|
@ -2104,19 +2105,17 @@ static const struct acpi_device_id tasdevice_acpi_match[] = {
|
|||
{ "TXNW5827", (kernel_ulong_t)&tasdevice_id[TAS5827] },
|
||||
{ "TXNW5828", (kernel_ulong_t)&tasdevice_id[TAS5828] },
|
||||
{ "TXNW5830", (kernel_ulong_t)&tasdevice_id[TAS5830] },
|
||||
{ "TXNW5832", (kernel_ulong_t)&tasdevice_id[TAS5832] },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, tasdevice_acpi_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver tasdevice_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tasdev-codec",
|
||||
.of_match_table = of_match_ptr(tasdevice_of_match),
|
||||
#ifdef CONFIG_ACPI
|
||||
.acpi_match_table = ACPI_PTR(tasdevice_acpi_match),
|
||||
#endif
|
||||
.of_match_table = tasdevice_of_match,
|
||||
.acpi_match_table = tasdevice_acpi_match,
|
||||
},
|
||||
.probe = tasdevice_i2c_probe,
|
||||
.remove = tasdevice_i2c_remove,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,29 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
{
|
||||
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_jack *dp_jack = NULL;
|
||||
int dp_pcm_id = 0;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
/*
|
||||
* Set limit of -3 dB on Digital Volume and 0 dB on PA Volume
|
||||
* to reduce the risk of speaker damage until we have active
|
||||
* speaker protection in place.
|
||||
*/
|
||||
snd_soc_limit_volume(card, "WSA WSA_RX0 Digital Volume", 81);
|
||||
snd_soc_limit_volume(card, "WSA WSA_RX1 Digital Volume", 81);
|
||||
snd_soc_limit_volume(card, "WSA2 WSA_RX0 Digital Volume", 81);
|
||||
snd_soc_limit_volume(card, "WSA2 WSA_RX1 Digital Volume", 81);
|
||||
snd_soc_limit_volume(card, "SpkrLeft PA Volume", 6);
|
||||
snd_soc_limit_volume(card, "SpkrRight PA Volume", 6);
|
||||
snd_soc_limit_volume(card, "WooferLeft PA Volume", 6);
|
||||
snd_soc_limit_volume(card, "TweeterLeft PA Volume", 6);
|
||||
snd_soc_limit_volume(card, "WooferRight PA Volume", 6);
|
||||
snd_soc_limit_volume(card, "TweeterRight PA Volume", 6);
|
||||
break;
|
||||
case DISPLAY_PORT_RX_0:
|
||||
dp_pcm_id = 0;
|
||||
dp_jack = &data->dp_jack[dp_pcm_id];
|
||||
|
|
|
|||
|
|
@ -1006,8 +1006,11 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
|
|||
control->has_fixed = true;
|
||||
fallthrough;
|
||||
case SDCA_ACCESS_MODE_RO:
|
||||
control->deferrable = fwnode_property_read_bool(control_node,
|
||||
"mipi-sdca-control-deferrable");
|
||||
ret = fwnode_property_read_u32(control_node,
|
||||
"mipi-sdca-control-deferrable",
|
||||
&tmp);
|
||||
if (ret == 0)
|
||||
control->deferrable = !!tmp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -40,12 +40,6 @@ static int asoc_sdw_bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
|
|||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s spk:cs35l56-bridge",
|
||||
card->components);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(dapm, bridge_widgets,
|
||||
ARRAY_SIZE(bridge_widgets));
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -107,21 +107,11 @@ EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, "SND_SOC_SDW_UTILS");
|
|||
|
||||
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
|
||||
if (!(ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS)) {
|
||||
/* Will be set by the bridge code in this case */
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s spk:cs42l43-spk",
|
||||
card->components);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = snd_soc_limit_volume(card, "cs42l43 Speaker Digital Volume",
|
||||
CS42L43_SPK_VOLUME_0DB);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -758,6 +758,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
|
|||
{
|
||||
.direction = {true, false},
|
||||
.codec_name = "cs42l43-codec",
|
||||
.component_name = "cs42l43-spk",
|
||||
.dai_name = "cs42l43-dp6",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
|
|
@ -1104,6 +1105,7 @@ static int asoc_sdw_find_codec_info_dai_index(const struct asoc_sdw_codec_info *
|
|||
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
struct snd_soc_dai *dai;
|
||||
|
|
@ -1179,16 +1181,26 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
/* Generate the spk component string for card->components string */
|
||||
if (codec_info->dais[dai_index].dai_type == SOC_SDW_DAI_TYPE_AMP &&
|
||||
codec_info->dais[dai_index].component_name) {
|
||||
const char *component;
|
||||
|
||||
/*
|
||||
* For the special case of cs42l43 with sidecar amps, use only
|
||||
* "cs35l56-bridge" as the component name in card->components
|
||||
*/
|
||||
if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS &&
|
||||
!strcmp(codec_info->dais[dai_index].component_name, "cs42l43-spk"))
|
||||
component = "cs35l56-bridge";
|
||||
else
|
||||
component = codec_info->dais[dai_index].component_name;
|
||||
|
||||
if (strlen (spk_components) == 0)
|
||||
spk_components =
|
||||
devm_kasprintf(card->dev, GFP_KERNEL, "%s",
|
||||
codec_info->dais[dai_index].component_name);
|
||||
devm_kasprintf(card->dev, GFP_KERNEL, "%s", component);
|
||||
else
|
||||
/* Append component name to spk_components */
|
||||
spk_components =
|
||||
devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s+%s", spk_components,
|
||||
codec_info->dais[dai_index].component_name);
|
||||
"%s+%s", spk_components, component);
|
||||
}
|
||||
|
||||
codec_info->dais[dai_index].rtd_init_done = true;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ const struct sof_intel_dsp_desc nvl_chip_info = {
|
|||
.power_down_dsp = mtl_power_down_dsp,
|
||||
.disable_interrupts = lnl_dsp_disable_interrupts,
|
||||
.hw_ip_version = SOF_INTEL_ACE_4_0,
|
||||
.platform = "nvl",
|
||||
};
|
||||
|
||||
const struct sof_intel_dsp_desc nvl_s_chip_info = {
|
||||
|
|
@ -72,6 +73,7 @@ const struct sof_intel_dsp_desc nvl_s_chip_info = {
|
|||
.power_down_dsp = mtl_power_down_dsp,
|
||||
.disable_interrupts = lnl_dsp_disable_interrupts,
|
||||
.hw_ip_version = SOF_INTEL_ACE_4_0,
|
||||
.platform = "nvl",
|
||||
};
|
||||
|
||||
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
|
|||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
|
||||
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
|
||||
static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
|
||||
static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
|
||||
|
||||
module_param_array(index, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for the 6fire sound device");
|
||||
|
|
@ -44,32 +43,28 @@ static DEFINE_MUTEX(register_mutex);
|
|||
|
||||
static void usb6fire_chip_abort(struct sfire_chip *chip)
|
||||
{
|
||||
if (chip) {
|
||||
if (chip->pcm)
|
||||
usb6fire_pcm_abort(chip);
|
||||
if (chip->midi)
|
||||
usb6fire_midi_abort(chip);
|
||||
if (chip->comm)
|
||||
usb6fire_comm_abort(chip);
|
||||
if (chip->control)
|
||||
usb6fire_control_abort(chip);
|
||||
}
|
||||
if (chip->pcm)
|
||||
usb6fire_pcm_abort(chip);
|
||||
if (chip->midi)
|
||||
usb6fire_midi_abort(chip);
|
||||
if (chip->comm)
|
||||
usb6fire_comm_abort(chip);
|
||||
if (chip->control)
|
||||
usb6fire_control_abort(chip);
|
||||
}
|
||||
|
||||
static void usb6fire_card_free(struct snd_card *card)
|
||||
{
|
||||
struct sfire_chip *chip = card->private_data;
|
||||
|
||||
if (chip) {
|
||||
if (chip->pcm)
|
||||
usb6fire_pcm_destroy(chip);
|
||||
if (chip->midi)
|
||||
usb6fire_midi_destroy(chip);
|
||||
if (chip->comm)
|
||||
usb6fire_comm_destroy(chip);
|
||||
if (chip->control)
|
||||
usb6fire_control_destroy(chip);
|
||||
}
|
||||
if (chip->pcm)
|
||||
usb6fire_pcm_destroy(chip);
|
||||
if (chip->midi)
|
||||
usb6fire_midi_destroy(chip);
|
||||
if (chip->comm)
|
||||
usb6fire_comm_destroy(chip);
|
||||
if (chip->control)
|
||||
usb6fire_control_destroy(chip);
|
||||
}
|
||||
|
||||
static int usb6fire_chip_probe(struct usb_interface *intf,
|
||||
|
|
@ -83,21 +78,18 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
|
|||
struct snd_card *card = NULL;
|
||||
|
||||
/* look if we already serve this card and return if so */
|
||||
scoped_guard(mutex, ®ister_mutex) {
|
||||
for (i = 0; i < SNDRV_CARDS; i++) {
|
||||
if (devices[i] == device) {
|
||||
if (chips[i])
|
||||
chips[i]->intf_count++;
|
||||
usb_set_intfdata(intf, chips[i]);
|
||||
return 0;
|
||||
} else if (!devices[i] && regidx < 0)
|
||||
regidx = i;
|
||||
}
|
||||
if (regidx < 0) {
|
||||
dev_err(&intf->dev, "too many cards registered.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
devices[regidx] = device;
|
||||
guard(mutex)(®ister_mutex);
|
||||
for (i = 0; i < SNDRV_CARDS; i++) {
|
||||
if (chips[i] && chips[i]->dev == device) {
|
||||
chips[i]->intf_count++;
|
||||
usb_set_intfdata(intf, chips[i]);
|
||||
return 0;
|
||||
} else if (!chips[i] && regidx < 0)
|
||||
regidx = i;
|
||||
}
|
||||
if (regidx < 0) {
|
||||
dev_err(&intf->dev, "too many cards registered.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* check, if firmware is present on device, upload it if not */
|
||||
|
|
@ -124,7 +116,6 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
|
|||
device->bus->busnum, device->devnum);
|
||||
|
||||
chip = card->private_data;
|
||||
chips[regidx] = chip;
|
||||
chip->dev = device;
|
||||
chip->regidx = regidx;
|
||||
chip->intf_count = 1;
|
||||
|
|
@ -152,7 +143,10 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
|
|||
dev_err(&intf->dev, "cannot register card.");
|
||||
goto destroy_chip;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, chip);
|
||||
chips[regidx] = chip;
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_chip:
|
||||
|
|
@ -165,30 +159,31 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
|
|||
struct sfire_chip *chip;
|
||||
struct snd_card *card;
|
||||
|
||||
guard(mutex)(®ister_mutex);
|
||||
chip = usb_get_intfdata(intf);
|
||||
if (chip) { /* if !chip, fw upload has been performed */
|
||||
chip->intf_count--;
|
||||
if (!chip->intf_count) {
|
||||
scoped_guard(mutex, ®ister_mutex) {
|
||||
devices[chip->regidx] = NULL;
|
||||
chips[chip->regidx] = NULL;
|
||||
}
|
||||
/* if !chip, fw upload has been performed */
|
||||
if (!chip)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Save card pointer before teardown.
|
||||
* snd_card_free_when_closed() may free card (and
|
||||
* the embedded chip) immediately, so it must be
|
||||
* called last and chip must not be accessed after.
|
||||
*/
|
||||
card = chip->card;
|
||||
chip->shutdown = true;
|
||||
if (card)
|
||||
snd_card_disconnect(card);
|
||||
usb6fire_chip_abort(chip);
|
||||
if (card)
|
||||
snd_card_free_when_closed(card);
|
||||
}
|
||||
}
|
||||
chip->intf_count--;
|
||||
if (chip->intf_count)
|
||||
return;
|
||||
|
||||
chips[chip->regidx] = NULL;
|
||||
|
||||
/*
|
||||
* Save card pointer before teardown.
|
||||
* snd_card_free_when_closed() may free card (and
|
||||
* the embedded chip) immediately, so it must be
|
||||
* called last and chip must not be accessed after.
|
||||
*/
|
||||
card = chip->card;
|
||||
chip->shutdown = true;
|
||||
if (card)
|
||||
snd_card_disconnect(card);
|
||||
usb6fire_chip_abort(chip);
|
||||
if (card)
|
||||
snd_card_free_when_closed(card);
|
||||
}
|
||||
|
||||
static const struct usb_device_id device_table[] = {
|
||||
|
|
|
|||
|
|
@ -290,15 +290,17 @@ static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
|
||||
int vol0 = ucontrol->value.integer.value[0] - 15;
|
||||
int vol1 = ucontrol->value.integer.value[1] - 15;
|
||||
int changed = 0;
|
||||
|
||||
if (rt->input_vol[0] != ucontrol->value.integer.value[0]) {
|
||||
rt->input_vol[0] = ucontrol->value.integer.value[0] - 15;
|
||||
if (rt->input_vol[0] != vol0) {
|
||||
rt->input_vol[0] = vol0;
|
||||
rt->ivol_updated &= ~(1 << 0);
|
||||
changed = 1;
|
||||
}
|
||||
if (rt->input_vol[1] != ucontrol->value.integer.value[1]) {
|
||||
rt->input_vol[1] = ucontrol->value.integer.value[1] - 15;
|
||||
if (rt->input_vol[1] != vol1) {
|
||||
rt->input_vol[1] = vol1;
|
||||
rt->ivol_updated &= ~(1 << 1);
|
||||
changed = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card);
|
||||
int pos = kcontrol->private_value;
|
||||
int v = ucontrol->value.integer.value[0];
|
||||
int ret;
|
||||
unsigned char cmd;
|
||||
|
||||
switch (cdev->chip.usb_id) {
|
||||
|
|
@ -103,6 +104,10 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
|
||||
if (pos & CNT_INTVAL) {
|
||||
int i = pos & ~CNT_INTVAL;
|
||||
unsigned char old = cdev->control_state[i];
|
||||
|
||||
if (old == v)
|
||||
return 0;
|
||||
|
||||
cdev->control_state[i] = v;
|
||||
|
||||
|
|
@ -113,10 +118,11 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
cdev->ep8_out_buf[0] = i;
|
||||
cdev->ep8_out_buf[1] = v;
|
||||
|
||||
usb_bulk_msg(cdev->chip.dev,
|
||||
usb_sndbulkpipe(cdev->chip.dev, 8),
|
||||
cdev->ep8_out_buf, sizeof(cdev->ep8_out_buf),
|
||||
&actual_len, 200);
|
||||
ret = usb_bulk_msg(cdev->chip.dev,
|
||||
usb_sndbulkpipe(cdev->chip.dev, 8),
|
||||
cdev->ep8_out_buf,
|
||||
sizeof(cdev->ep8_out_buf),
|
||||
&actual_len, 200);
|
||||
} else if (cdev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER)) {
|
||||
|
||||
|
|
@ -128,21 +134,36 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
offset = MASCHINE_BANK_SIZE;
|
||||
}
|
||||
|
||||
snd_usb_caiaq_send_command_bank(cdev, cmd, bank,
|
||||
cdev->control_state + offset,
|
||||
MASCHINE_BANK_SIZE);
|
||||
ret = snd_usb_caiaq_send_command_bank(cdev, cmd, bank,
|
||||
cdev->control_state + offset,
|
||||
MASCHINE_BANK_SIZE);
|
||||
} else {
|
||||
snd_usb_caiaq_send_command(cdev, cmd,
|
||||
cdev->control_state, sizeof(cdev->control_state));
|
||||
ret = snd_usb_caiaq_send_command(cdev, cmd,
|
||||
cdev->control_state,
|
||||
sizeof(cdev->control_state));
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
cdev->control_state[i] = old;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (v)
|
||||
cdev->control_state[pos / 8] |= 1 << (pos % 8);
|
||||
else
|
||||
cdev->control_state[pos / 8] &= ~(1 << (pos % 8));
|
||||
int idx = pos / 8;
|
||||
unsigned char mask = 1 << (pos % 8);
|
||||
unsigned char old = cdev->control_state[idx];
|
||||
unsigned char val = v ? (old | mask) : (old & ~mask);
|
||||
|
||||
snd_usb_caiaq_send_command(cdev, cmd,
|
||||
cdev->control_state, sizeof(cdev->control_state));
|
||||
if (old == val)
|
||||
return 0;
|
||||
|
||||
cdev->control_state[idx] = val;
|
||||
ret = snd_usb_caiaq_send_command(cdev, cmd,
|
||||
cdev->control_state,
|
||||
sizeof(cdev->control_state));
|
||||
if (ret < 0) {
|
||||
cdev->control_state[idx] = old;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
@ -640,4 +661,3 @@ int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *cdev)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *cdev,
|
|||
tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static void setup_card(struct snd_usb_caiaqdev *cdev)
|
||||
static int setup_card(struct snd_usb_caiaqdev *cdev)
|
||||
{
|
||||
int ret;
|
||||
char val[4];
|
||||
|
|
@ -325,8 +325,10 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
|
|||
snd_usb_caiaq_send_command(cdev, EP1_CMD_READ_IO, NULL, 0);
|
||||
|
||||
if (!wait_event_timeout(cdev->ep1_wait_queue,
|
||||
cdev->control_state[0] != 0xff, HZ))
|
||||
return;
|
||||
cdev->control_state[0] != 0xff, HZ)) {
|
||||
dev_err(dev, "Read timeout for control state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* fix up some defaults */
|
||||
if ((cdev->control_state[1] != 2) ||
|
||||
|
|
@ -347,33 +349,43 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
|
|||
cdev->spec.num_digital_audio_out +
|
||||
cdev->spec.num_digital_audio_in > 0) {
|
||||
ret = snd_usb_caiaq_audio_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up audio system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (cdev->spec.num_midi_in +
|
||||
cdev->spec.num_midi_out > 0) {
|
||||
ret = snd_usb_caiaq_midi_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up MIDI system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
|
||||
ret = snd_usb_caiaq_input_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up input system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* finally, register the card and all its sub-instances */
|
||||
ret = snd_card_register(cdev->chip.card);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "snd_card_register() returned %d\n", ret);
|
||||
snd_card_free(cdev->chip.card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_usb_caiaq_control_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void card_free(struct snd_card *card)
|
||||
|
|
@ -499,8 +511,11 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|||
scnprintf(card->longname, sizeof(card->longname), "%s %s (%s)",
|
||||
cdev->vendor_name, cdev->product_name, usbpath);
|
||||
|
||||
setup_card(cdev);
|
||||
card->private_free = card_free;
|
||||
err = setup_card(cdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
err_kill_urb:
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
|
|||
nr_rates++;
|
||||
if (nr_rates >= MAX_NR_RATES) {
|
||||
usb_audio_err(chip, "invalid uac2 rates\n");
|
||||
break;
|
||||
return nr_rates;
|
||||
}
|
||||
|
||||
skip_rate:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ enum {
|
|||
LINE6_PODHD500X,
|
||||
LINE6_PODHDDESKTOP,
|
||||
LINE6_PODHDPROX,
|
||||
LINE6_PODHDPRO,
|
||||
};
|
||||
|
||||
struct usb_line6_podhd {
|
||||
|
|
@ -442,6 +443,7 @@ static const struct usb_device_id podhd_id_table[] = {
|
|||
{ LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X },
|
||||
{ LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP },
|
||||
{ LINE6_IF_NUM(0x415A, 0), .driver_info = LINE6_PODHDPROX },
|
||||
{ LINE6_IF_NUM(0x4157, 0), .driver_info = LINE6_PODHDPRO },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
@ -542,6 +544,18 @@ static const struct line6_properties podhd_properties_table[] = {
|
|||
.ep_audio_r = 0x86,
|
||||
.ep_audio_w = 0x02,
|
||||
},
|
||||
[LINE6_PODHDPRO] = {
|
||||
.id = "PODHDPRO",
|
||||
.name = "POD HD PRO",
|
||||
.capabilities = LINE6_CAP_PCM | LINE6_CAP_CONTROL
|
||||
| LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL | LINE6_CAP_IN_NEEDS_OUT,
|
||||
.altsetting = 1,
|
||||
.ctrl_if = 1,
|
||||
.ep_ctrl_r = 0x81,
|
||||
.ep_ctrl_w = 0x01,
|
||||
.ep_audio_r = 0x86,
|
||||
.ep_audio_w = 0x02,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2664,6 +2664,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|||
|
||||
/* get min/max values */
|
||||
switch (type) {
|
||||
case USB_XU_CLOCK_RATE:
|
||||
/*
|
||||
* E-Mu USB 0404/0202/TrackerPre/0204
|
||||
* samplerate control quirk
|
||||
*/
|
||||
cval->min = 0;
|
||||
cval->max = 5;
|
||||
cval->res = 1;
|
||||
cval->initialized = 1;
|
||||
break;
|
||||
case UAC_PROCESS_UP_DOWNMIX: {
|
||||
bool mode_sel = false;
|
||||
|
||||
|
|
@ -2687,31 +2697,17 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|||
cval->max = control_spec[0];
|
||||
cval->res = 1;
|
||||
cval->initialized = 1;
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
err = get_min_max(cval, valinfo->min_value);
|
||||
break;
|
||||
fallthrough;
|
||||
}
|
||||
case USB_XU_CLOCK_RATE:
|
||||
/*
|
||||
* E-Mu USB 0404/0202/TrackerPre/0204
|
||||
* samplerate control quirk
|
||||
*/
|
||||
cval->min = 0;
|
||||
cval->max = 5;
|
||||
cval->res = 1;
|
||||
cval->initialized = 1;
|
||||
err = 0;
|
||||
break;
|
||||
default:
|
||||
err = get_min_max(cval, valinfo->min_value);
|
||||
break;
|
||||
}
|
||||
if (err < 0 && err != -EAGAIN) {
|
||||
usb_mixer_elem_info_free(cval);
|
||||
return err;
|
||||
if (err < 0 && err != -EAGAIN) {
|
||||
usb_mixer_elem_info_free(cval);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = get_cur_ctl_value(cval, cval->control << 8, &val);
|
||||
|
|
|
|||
|
|
@ -1538,15 +1538,17 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
|
|||
{
|
||||
struct usb_mixer_interface *mixer;
|
||||
struct usb_mixer_elem_info *cval;
|
||||
int err;
|
||||
int unitid = 12; /* SampleRate ExtensionUnit ID */
|
||||
|
||||
list_for_each_entry(mixer, &chip->mixer_list, list) {
|
||||
if (mixer->id_elems[unitid]) {
|
||||
cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
|
||||
snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
|
||||
cval->control << 8,
|
||||
samplerate_id);
|
||||
snd_usb_mixer_notify_id(mixer, unitid);
|
||||
err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
|
||||
cval->control << 8,
|
||||
samplerate_id);
|
||||
if (!err)
|
||||
snd_usb_mixer_notify_id(mixer, unitid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2025,7 +2027,7 @@ static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol,
|
|||
int err;
|
||||
|
||||
reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a;
|
||||
if (reg != list->kctl->private_value)
|
||||
if (reg == list->kctl->private_value)
|
||||
return 0;
|
||||
|
||||
kcontrol->private_value = reg;
|
||||
|
|
|
|||
|
|
@ -2474,6 +2474,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
|||
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
|
||||
DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */
|
||||
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
|
||||
DEVICE_FLG(0x3443, 0x930d, /* NexiGo N930W 60fps Webcam */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
|
||||
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ struct virtio_pcm_msg;
|
|||
* the device side at resume.
|
||||
* @msgs: Allocated I/O messages.
|
||||
* @nmsgs: Number of allocated I/O messages.
|
||||
* @msg_last_enqueued: Index of the last I/O message added to the virtqueue.
|
||||
* @msg_count: Number of pending I/O messages in the virtqueue.
|
||||
* @msg_empty: Notify when msg_count is zero.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user