summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/core/pcm_native.c7
-rw-r--r--sound/core/seq/seq_dummy.c15
-rw-r--r--sound/soc/amd/acp-config.c7
-rw-r--r--sound/soc/amd/acp/amd-acp70-acpi-match.c44
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c14
-rw-r--r--sound/soc/fsl/fsl_sai.c2
-rw-r--r--sound/usb/mixer.c33
-rw-r--r--sound/usb/quirks.c2
8 files changed, 109 insertions, 15 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a541bb235cfa..302643c1c192 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2199,9 +2199,8 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
drain_no_period_wakeup = to_check->no_period_wakeup;
drain_rate = to_check->rate;
drain_bufsz = to_check->buffer_size;
- init_waitqueue_entry(&wait, current);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&to_check->sleep, &wait);
+ init_wait_entry(&wait, 0);
+ prepare_to_wait(&to_check->sleep, &wait, TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
if (drain_no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
@@ -2219,7 +2218,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
group = snd_pcm_stream_group_ref(substream);
snd_pcm_group_for_each_entry(s, substream) {
if (s->runtime == to_check) {
- remove_wait_queue(&to_check->sleep, &wait);
+ finish_wait(&to_check->sleep, &wait);
break;
}
}
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index af45f328ae99..8abe80985dad 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <sound/core.h>
#include "seq_clientmgr.h"
+#include "seq_memory.h"
#include <sound/initval.h>
#include <sound/asoundef.h>
@@ -81,19 +82,21 @@ dummy_input(struct snd_seq_event *ev, int direct, void *private_data,
int atomic, int hop)
{
struct snd_seq_dummy_port *p;
- struct snd_seq_event tmpev;
+ union __snd_seq_event tmpev;
+ size_t size;
p = private_data;
if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
return 0; /* ignore system messages */
- tmpev = *ev;
+ size = snd_seq_event_packet_size(ev);
+ memcpy(&tmpev, ev, size);
if (p->duplex)
- tmpev.source.port = p->connect;
+ tmpev.legacy.source.port = p->connect;
else
- tmpev.source.port = p->port;
- tmpev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- return snd_seq_kernel_client_dispatch(p->client, &tmpev, atomic, hop);
+ tmpev.legacy.source.port = p->port;
+ tmpev.legacy.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
+ return snd_seq_kernel_client_dispatch(p->client, &tmpev.legacy, atomic, hop);
}
/*
diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c
index 309dc9ed6e0d..0d977f4f758d 100644
--- a/sound/soc/amd/acp-config.c
+++ b/sound/soc/amd/acp-config.c
@@ -37,6 +37,13 @@ static const struct dmi_system_id acp70_acpi_flag_override_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Zenbook S16 UM5606GA"),
},
},
+ {
+ /* Lenovo Yoga Pro 7 15ASH11 (Strix Halo, ACP 7.0) */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83W5"),
+ },
+ },
{}
};
diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c
index 1ae43df5da6c..18f2918d4ada 100644
--- a/sound/soc/amd/acp/amd-acp70-acpi-match.c
+++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c
@@ -619,6 +619,45 @@ static const struct snd_soc_acpi_link_adr acp70_rt721_l1u0_tas2783x2_l1u8b[] = {
{}
};
+static const struct snd_soc_acpi_endpoint rt721_endpoints[] = {
+ { /* Jack Playback/Capture Endpoint (AIF1) */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Amplifier Endpoint (AIF2, internal amp) */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint (AIF3) */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt721_1_single_adr[] = {
+ {
+ .adr = 0x000130025D072101ull,
+ .num_endpoints = ARRAY_SIZE(rt721_endpoints),
+ .endpoints = rt721_endpoints,
+ .name_prefix = "rt721"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp70_rt721_only[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt721_1_single_adr),
+ .adr_d = rt721_1_single_adr,
+ },
+ {}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = {
{
.link_mask = BIT(0) | BIT(1),
@@ -711,6 +750,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = {
.links = acp70_rt721_l1u0_tas2783x2_l1u8b,
.drv_name = "amd_sdw",
},
+ {
+ .link_mask = BIT(1),
+ .links = acp70_rt721_only,
+ .drv_name = "amd_sdw",
+ },
{},
};
EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sdw_machines);
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 7a637d6b5576..b426cda529a9 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -524,6 +524,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Raider A18 HX A9WJG"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
}
@@ -794,6 +801,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "M7601RM"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-17LN"),
+ }
+ },
{}
};
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index e364552c1f47..78e953cd3e9f 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -793,7 +793,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR);
regmap_write(sai->regmap, FSL_SAI_xMR(tx),
- ~0UL - ((1 << min(channels, slots)) - 1));
+ ~GENMASK_U32(min(channels, slots) - 1, 0));
return 0;
}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 5fba456eb4a9..fb37bb8ad9a9 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1371,10 +1371,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
goto no_checks;
ret = check_sticky_volume_control(cval, minchn, saved);
- if (ret < 0) {
- snd_usb_set_cur_mix_value(cval, minchn, 0, saved);
- return ret;
- }
+ if (ret < 0)
+ goto sticky;
if (cval->min + cval->res < cval->max)
check_volume_control_res(cval, minchn, saved);
@@ -1431,6 +1429,33 @@ no_checks:
}
return 0;
+
+sticky:
+ /*
+ * It makes no sense to restore the saved value for a sticky mixer,
+ * since setting any value is a no-op.
+ *
+ * However, in some rare cases, SET_CUR is effective despite GET_CUR
+ * always returns a constant value. These mixers are not sticky, but
+ * there's no way to distinguish them. Without any additional
+ * information, the best thing we can do is to set the mixer value to
+ * the maximum before bailing out, so that a soft mixer can still reach
+ * the maximum hardware volume if the mixer turns out to be non-sticky.
+ * Meanwhile, all channels must be synchronized to prevent imbalance
+ * volume.
+ */
+ if (!cval->cmask) {
+ snd_usb_set_cur_mix_value(cval, 0, 0, cval->max);
+ } else {
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ idx = 0;
+ if (cval->cmask & BIT(i)) {
+ snd_usb_set_cur_mix_value(cval, i + 1, idx, cval->max);
+ idx++;
+ }
+ }
+ }
+ return ret;
}
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 3d1b3523b020..f4e885f96e83 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2487,6 +2487,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
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(0x3c20, 0x3d21, /* AB13X USB Audio */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */