summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 11:55:28 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 11:55:28 -0800
commit7912a6391f3ee7eb9f9a69227a209d502679bc0c (patch)
tree38be70147934f98cde0ccef0ba65b836246e4d0d /sound/core
parentcf65598d5909acf5e7b7dc9e21786e386356bc81 (diff)
parentfd38dd6abda589a8771e7872e4dea28c99c6a6ef (diff)
Merge tag 'sound-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "It was a calm development cycle. There were an ALSA core extension for subformat PCM bits and a few ASoC core changes to support N:M mappings, while the most of remaining changes are driver-specific. Core: - API extensions for properly limiting PCM format bits via subformat - Enhanced support for N:M CPU:CODEC mappings in the core and in audio-graph-card2 ASoC: - Lots of SOF updates: fallback support to older IPC versions, notification on control changes with IPC4. Also supports for ACPI parse for the ES83xx driver that reduces quirks. - Device tree support for describing parts of the card which can be active over suspend (for very low power playback or wake word use cases) - Support for more AMD and Intel systems, NXP i.MX8m MICFIL, Qualcomm SM8250, SM8550, SM8650 and X1E80100 - Drop of Freescale MPC8610 code that is no longer supported HD-audio: - More CS35L41 codec extensions for Dell, HP and Lenovo models - TAS2781 codec extensions for Lenovo and co - New PCM subformat supports Others: - More enhancement for Scarlett2 USB mixer support - Various kselftest fixes" * tag 'sound-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (337 commits) kselftest/alsa - conf: Stringify the printed errno in sysfs_get() kselftest/alsa - mixer-test: Fix the print format specifier warning kselftest/alsa - mixer-test: Fix the print format specifier warning kselftest/alsa - mixer-test: fix the number of parameters to ksft_exit_fail_msg() ALSA: hda/tas2781: annotate calibration data endianness ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP Envy X360 13-ay0xxx ALSA: hda/conexant: Fix headset auto detect fail in cx8070 and SN6140 ALSA: ac97: fix build regression ALSA: hda: cs35l41: Support more HP models without _DSD ALSA: hda/tas2781: add fixup for Lenovo 14ARB7 ALSA: hda/tas2781: add TAS2563 support for 14ARB7 ALSA: hda/tas2781: add configurable global i2c address ALSA: hda/tas2781: add ptrs to calibration functions ALSA: hda: Add driver properties for cs35l41 for Lenovo Legion Slim 7 Gen 8 serie ALSA: hda/realtek: enable SND_PCI_QUIRK for Lenovo Legion Slim 7 Gen 8 (2023) serie ALSA: hda/tas2781: configure the amp after firmware load ALSA: mark all struct bus_type as const ASoC: pxa: sspa: Don't select SND_ARM ASoC: rt5663: cancel the work when system suspends ALSA: scarlett2: Add PCM Input Switch for Solo Gen 4 ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm.c3
-rw-r--r--sound/core/pcm_lib.c34
-rw-r--r--sound/core/pcm_native.c55
-rw-r--r--sound/core/seq/seq_memory.c3
4 files changed, 92 insertions, 3 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 6d0c9c37796c..a09f0154e6a7 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -266,6 +266,9 @@ static const char * const snd_pcm_access_names[] = {
static const char * const snd_pcm_subformat_names[] = {
SUBFORMAT(STD),
+ SUBFORMAT(MSBITS_MAX),
+ SUBFORMAT(MSBITS_20),
+ SUBFORMAT(MSBITS_24),
};
static const char * const snd_pcm_tstamp_mode_names[] = {
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index a11cd7d6295f..41103e5c43ce 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1706,6 +1706,40 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
}
EXPORT_SYMBOL(snd_pcm_hw_param_last);
+/**
+ * snd_pcm_hw_params_bits - Get the number of bits per the sample.
+ * @p: hardware parameters
+ *
+ * Return: The number of bits per sample based on the format,
+ * subformat and msbits the specified hw params has.
+ */
+int snd_pcm_hw_params_bits(const struct snd_pcm_hw_params *p)
+{
+ snd_pcm_subformat_t subformat = params_subformat(p);
+ snd_pcm_format_t format = params_format(p);
+
+ switch (format) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_U32_LE:
+ case SNDRV_PCM_FORMAT_S32_BE:
+ case SNDRV_PCM_FORMAT_U32_BE:
+ switch (subformat) {
+ case SNDRV_PCM_SUBFORMAT_MSBITS_20:
+ return 20;
+ case SNDRV_PCM_SUBFORMAT_MSBITS_24:
+ return 24;
+ case SNDRV_PCM_SUBFORMAT_MSBITS_MAX:
+ case SNDRV_PCM_SUBFORMAT_STD:
+ default:
+ break;
+ }
+ fallthrough;
+ default:
+ return snd_pcm_format_width(format);
+ }
+}
+EXPORT_SYMBOL(snd_pcm_hw_params_bits);
+
static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
void *arg)
{
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index f610b08f5a2b..f5ff00f99788 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -479,6 +479,7 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
{
const struct snd_interval *i;
const struct snd_mask *m;
+ struct snd_mask *m_rw;
int err;
if (!params->msbits) {
@@ -487,6 +488,22 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
params->msbits = snd_interval_value(i);
}
+ if (params->msbits) {
+ m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ if (snd_mask_single(m)) {
+ snd_pcm_format_t format = (__force snd_pcm_format_t)snd_mask_min(m);
+
+ if (snd_pcm_format_linear(format) &&
+ snd_pcm_format_width(format) != params->msbits) {
+ m_rw = hw_param_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT);
+ snd_mask_reset(m_rw,
+ (__force unsigned)SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
+ if (snd_mask_empty(m_rw))
+ return -EINVAL;
+ }
+ }
+ }
+
if (!params->rate_den) {
i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
if (snd_interval_single(i)) {
@@ -2483,6 +2500,41 @@ static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
+static int snd_pcm_hw_rule_subformats(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct snd_mask *sfmask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT);
+ struct snd_mask *fmask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ u32 *subformats = rule->private;
+ snd_pcm_format_t f;
+ struct snd_mask m;
+
+ snd_mask_none(&m);
+ /* All PCMs support at least the default STD subformat. */
+ snd_mask_set(&m, (__force unsigned)SNDRV_PCM_SUBFORMAT_STD);
+
+ pcm_for_each_format(f) {
+ if (!snd_mask_test(fmask, (__force unsigned)f))
+ continue;
+
+ if (f == SNDRV_PCM_FORMAT_S32_LE && *subformats)
+ m.bits[0] |= *subformats;
+ else if (snd_pcm_format_linear(f))
+ snd_mask_set(&m, (__force unsigned)SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
+ }
+
+ return snd_mask_refine(sfmask, &m);
+}
+
+static int snd_pcm_hw_constraint_subformats(struct snd_pcm_runtime *runtime,
+ unsigned int cond, u32 *subformats)
+{
+ return snd_pcm_hw_rule_add(runtime, cond, -1,
+ snd_pcm_hw_rule_subformats, (void *)subformats,
+ SNDRV_PCM_HW_PARAM_SUBFORMAT,
+ SNDRV_PCM_HW_PARAM_FORMAT, -1);
+}
+
static int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2634,8 +2686,7 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
if (err < 0)
return err;
- err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT,
- PARAM_MASK_BIT(SNDRV_PCM_SUBFORMAT_STD));
+ err = snd_pcm_hw_constraint_subformats(runtime, 0, &hw->subformats);
if (err < 0)
return err;
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index b603bb93f896..e705e7538118 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -442,7 +442,8 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
if (snd_BUG_ON(!pool))
return -EINVAL;
- cellptr = kvmalloc_array(sizeof(struct snd_seq_event_cell), pool->size,
+ cellptr = kvmalloc_array(pool->size,
+ sizeof(struct snd_seq_event_cell),
GFP_KERNEL);
if (!cellptr)
return -ENOMEM;