mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Merge branch 'topic/format-kunit' into for-next
Pull ALSA core kunit test. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
8b87a7863f
@ -20485,6 +20485,12 @@ F: include/uapi/sound/compress_*
|
||||
F: sound/core/compress_offload.c
|
||||
F: sound/soc/soc-compress.c
|
||||
|
||||
SOUND - CORE KUNIT TEST
|
||||
M: Ivan Orlov <ivan.orlov0322@gmail.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Supported
|
||||
F: sound/core/sound_kunit.c
|
||||
|
||||
SOUND - DMAENGINE HELPERS
|
||||
M: Lars-Peter Clausen <lars@metafoo.de>
|
||||
S: Supported
|
||||
|
@ -39,6 +39,22 @@ config SND_UMP_LEGACY_RAWMIDI
|
||||
legacy MIDI 1.0 byte streams is created for each UMP Endpoint.
|
||||
The device contains 16 substreams corresponding to UMP groups.
|
||||
|
||||
config SND_CORE_TEST
|
||||
tristate "Sound core KUnit test"
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This options enables the sound core functions KUnit test.
|
||||
|
||||
KUnit tests run during boot and output the results to the debug
|
||||
log in TAP format (https://testanything.org/). Only useful for
|
||||
kernel devs running KUnit test harness and are not for inclusion
|
||||
into a production build.
|
||||
|
||||
For more information on KUnit and unit tests in general, refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
|
||||
config SND_COMPRESS_OFFLOAD
|
||||
tristate
|
||||
|
||||
|
@ -49,6 +49,8 @@ obj-$(CONFIG_SND_SEQ_DEVICE) += snd-seq-device.o
|
||||
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
|
||||
obj-$(CONFIG_SND_UMP) += snd-ump.o
|
||||
|
||||
obj-$(CONFIG_SND_CORE_TEST) += sound_kunit.o
|
||||
|
||||
obj-$(CONFIG_SND_OSSEMUL) += oss/
|
||||
obj-$(CONFIG_SND_SEQUENCER) += seq/
|
||||
|
||||
|
@ -211,6 +211,10 @@ static const char * const snd_pcm_format_names[] = {
|
||||
FORMAT(DSD_U32_LE),
|
||||
FORMAT(DSD_U16_BE),
|
||||
FORMAT(DSD_U32_BE),
|
||||
FORMAT(S20_LE),
|
||||
FORMAT(S20_BE),
|
||||
FORMAT(U20_LE),
|
||||
FORMAT(U20_BE),
|
||||
};
|
||||
|
||||
/**
|
||||
@ -221,9 +225,11 @@ static const char * const snd_pcm_format_names[] = {
|
||||
*/
|
||||
const char *snd_pcm_format_name(snd_pcm_format_t format)
|
||||
{
|
||||
if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
|
||||
unsigned int format_num = (__force unsigned int)format;
|
||||
|
||||
if (format_num >= ARRAY_SIZE(snd_pcm_format_names) || !snd_pcm_format_names[format_num])
|
||||
return "Unknown";
|
||||
return snd_pcm_format_names[(__force unsigned int)format];
|
||||
return snd_pcm_format_names[format_num];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_format_name);
|
||||
|
||||
|
310
sound/core/sound_kunit.c
Normal file
310
sound/core/sound_kunit.c
Normal file
@ -0,0 +1,310 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Sound core KUnit test
|
||||
* Author: Ivan Orlov <ivan.orlov0322@gmail.com>
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#define SILENCE_BUFFER_SIZE 2048
|
||||
#define SILENCE(...) { __VA_ARGS__ }
|
||||
#define DEFINE_FORMAT(fmt, pbits, wd, endianness, signd, silence_arr) { \
|
||||
.format = SNDRV_PCM_FORMAT_##fmt, .physical_bits = pbits, \
|
||||
.width = wd, .le = endianness, .sd = signd, .silence = silence_arr, \
|
||||
.name = #fmt, \
|
||||
}
|
||||
|
||||
#define WRONG_FORMAT (SNDRV_PCM_FORMAT_LAST + 1)
|
||||
|
||||
#define VALID_NAME "ValidName"
|
||||
#define NAME_W_SPEC_CHARS "In%v@1id name"
|
||||
#define NAME_W_SPACE "Test name"
|
||||
#define NAME_W_SPACE_REMOVED "Testname"
|
||||
|
||||
#define TEST_FIRST_COMPONENT "Component1"
|
||||
#define TEST_SECOND_COMPONENT "Component2"
|
||||
|
||||
struct snd_format_test_data {
|
||||
snd_pcm_format_t format;
|
||||
int physical_bits;
|
||||
int width;
|
||||
int le;
|
||||
int sd;
|
||||
unsigned char silence[8];
|
||||
unsigned char *name;
|
||||
};
|
||||
|
||||
struct avail_test_data {
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_pcm_uframes_t hw_ptr;
|
||||
snd_pcm_uframes_t appl_ptr;
|
||||
snd_pcm_uframes_t expected_avail;
|
||||
};
|
||||
|
||||
static struct snd_format_test_data valid_fmt[] = {
|
||||
DEFINE_FORMAT(S8, 8, 8, -1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U8, 8, 8, -1, 0, SILENCE(0x80)),
|
||||
DEFINE_FORMAT(S16_LE, 16, 16, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S16_BE, 16, 16, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U16_LE, 16, 16, 1, 0, SILENCE(0x00, 0x80)),
|
||||
DEFINE_FORMAT(U16_BE, 16, 16, 0, 0, SILENCE(0x80, 0x00)),
|
||||
DEFINE_FORMAT(S24_LE, 32, 24, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S24_BE, 32, 24, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U24_LE, 32, 24, 1, 0, SILENCE(0x00, 0x00, 0x80)),
|
||||
DEFINE_FORMAT(U24_BE, 32, 24, 0, 0, SILENCE(0x00, 0x80, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(S32_LE, 32, 32, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S32_BE, 32, 32, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U32_LE, 32, 32, 1, 0, SILENCE(0x00, 0x00, 0x00, 0x80)),
|
||||
DEFINE_FORMAT(U32_BE, 32, 32, 0, 0, SILENCE(0x80, 0x00, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(FLOAT_LE, 32, 32, 1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(FLOAT_BE, 32, 32, 0, -1, SILENCE()),
|
||||
DEFINE_FORMAT(FLOAT64_LE, 64, 64, 1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(FLOAT64_BE, 64, 64, 0, -1, SILENCE()),
|
||||
DEFINE_FORMAT(IEC958_SUBFRAME_LE, 32, 32, 1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(IEC958_SUBFRAME_BE, 32, 32, 0, -1, SILENCE()),
|
||||
DEFINE_FORMAT(MU_LAW, 8, 8, -1, -1, SILENCE(0x7f)),
|
||||
DEFINE_FORMAT(A_LAW, 8, 8, -1, -1, SILENCE(0x55)),
|
||||
DEFINE_FORMAT(IMA_ADPCM, 4, 4, -1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(G723_24, 3, 3, -1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(G723_40, 5, 5, -1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(DSD_U8, 8, 8, 1, 0, SILENCE(0x69)),
|
||||
DEFINE_FORMAT(DSD_U16_LE, 16, 16, 1, 0, SILENCE(0x69, 0x69)),
|
||||
DEFINE_FORMAT(DSD_U32_LE, 32, 32, 1, 0, SILENCE(0x69, 0x69, 0x69, 0x69)),
|
||||
DEFINE_FORMAT(DSD_U16_BE, 16, 16, 0, 0, SILENCE(0x69, 0x69)),
|
||||
DEFINE_FORMAT(DSD_U32_BE, 32, 32, 0, 0, SILENCE(0x69, 0x69, 0x69, 0x69)),
|
||||
DEFINE_FORMAT(S20_LE, 32, 20, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S20_BE, 32, 20, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U20_LE, 32, 20, 1, 0, SILENCE(0x00, 0x00, 0x08, 0x00)),
|
||||
DEFINE_FORMAT(U20_BE, 32, 20, 0, 0, SILENCE(0x00, 0x08, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(S24_3LE, 24, 24, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S24_3BE, 24, 24, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U24_3LE, 24, 24, 1, 0, SILENCE(0x00, 0x00, 0x80)),
|
||||
DEFINE_FORMAT(U24_3BE, 24, 24, 0, 0, SILENCE(0x80, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(S20_3LE, 24, 20, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S20_3BE, 24, 20, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U20_3LE, 24, 20, 1, 0, SILENCE(0x00, 0x00, 0x08)),
|
||||
DEFINE_FORMAT(U20_3BE, 24, 20, 0, 0, SILENCE(0x08, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(S18_3LE, 24, 18, 1, 1, SILENCE()),
|
||||
DEFINE_FORMAT(S18_3BE, 24, 18, 0, 1, SILENCE()),
|
||||
DEFINE_FORMAT(U18_3LE, 24, 18, 1, 0, SILENCE(0x00, 0x00, 0x02)),
|
||||
DEFINE_FORMAT(U18_3BE, 24, 18, 0, 0, SILENCE(0x02, 0x00, 0x00)),
|
||||
DEFINE_FORMAT(G723_24_1B, 8, 3, -1, -1, SILENCE()),
|
||||
DEFINE_FORMAT(G723_40_1B, 8, 5, -1, -1, SILENCE()),
|
||||
};
|
||||
|
||||
static void test_phys_format_size(struct kunit *test)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_fmt); i++) {
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_physical_width(valid_fmt[i].format),
|
||||
valid_fmt[i].physical_bits);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_physical_width(WRONG_FORMAT), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_physical_width(-1), -EINVAL);
|
||||
}
|
||||
|
||||
static void test_format_width(struct kunit *test)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_fmt); i++) {
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_width(valid_fmt[i].format),
|
||||
valid_fmt[i].width);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_width(WRONG_FORMAT), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_width(-1), -EINVAL);
|
||||
}
|
||||
|
||||
static void test_format_signed(struct kunit *test)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_fmt); i++) {
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_signed(valid_fmt[i].format),
|
||||
valid_fmt[i].sd < 0 ? -EINVAL : valid_fmt[i].sd);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_unsigned(valid_fmt[i].format),
|
||||
valid_fmt[i].sd < 0 ? -EINVAL : 1 - valid_fmt[i].sd);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_width(WRONG_FORMAT), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_width(-1), -EINVAL);
|
||||
}
|
||||
|
||||
static void test_format_endianness(struct kunit *test)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_fmt); i++) {
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_little_endian(valid_fmt[i].format),
|
||||
valid_fmt[i].le < 0 ? -EINVAL : valid_fmt[i].le);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_big_endian(valid_fmt[i].format),
|
||||
valid_fmt[i].le < 0 ? -EINVAL : 1 - valid_fmt[i].le);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_little_endian(WRONG_FORMAT), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_little_endian(-1), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_big_endian(WRONG_FORMAT), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_big_endian(-1), -EINVAL);
|
||||
}
|
||||
|
||||
static void _test_fill_silence(struct kunit *test, struct snd_format_test_data *data,
|
||||
u8 *buffer, size_t samples_count)
|
||||
{
|
||||
size_t sample_bytes = data->physical_bits >> 3;
|
||||
u32 i;
|
||||
|
||||
KUNIT_ASSERT_EQ(test, snd_pcm_format_set_silence(data->format, buffer, samples_count), 0);
|
||||
for (i = 0; i < samples_count * sample_bytes; i++)
|
||||
KUNIT_EXPECT_EQ(test, buffer[i], data->silence[i % sample_bytes]);
|
||||
}
|
||||
|
||||
static void test_format_fill_silence(struct kunit *test)
|
||||
{
|
||||
u32 buf_samples[] = { 10, 20, 32, 64, 129, 260 };
|
||||
u8 *buffer;
|
||||
u32 i, j;
|
||||
|
||||
buffer = kunit_kzalloc(test, SILENCE_BUFFER_SIZE, GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(buf_samples); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(valid_fmt); j++)
|
||||
_test_fill_silence(test, &valid_fmt[j], buffer, buf_samples[i]);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_set_silence(WRONG_FORMAT, buffer, 20), -EINVAL);
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_format_set_silence(SNDRV_PCM_FORMAT_LAST, buffer, 0), 0);
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t calculate_boundary(snd_pcm_uframes_t buffer_size)
|
||||
{
|
||||
snd_pcm_uframes_t boundary = buffer_size;
|
||||
|
||||
while (boundary * 2 <= 0x7fffffffUL - buffer_size)
|
||||
boundary *= 2;
|
||||
return boundary;
|
||||
}
|
||||
|
||||
static struct avail_test_data p_avail_data[] = {
|
||||
/* buf_size + hw_ptr < appl_ptr => avail = buf_size + hw_ptr - appl_ptr + boundary */
|
||||
{ 128, 1000, 1129, 1073741824UL - 1 },
|
||||
/*
|
||||
* buf_size + hw_ptr - appl_ptr >= boundary =>
|
||||
* => avail = buf_size + hw_ptr - appl_ptr - boundary
|
||||
*/
|
||||
{ 128, 1073741824UL, 10, 118 },
|
||||
/* standard case: avail = buf_size + hw_ptr - appl_ptr */
|
||||
{ 128, 1000, 1001, 127 },
|
||||
};
|
||||
|
||||
static void test_playback_avail(struct kunit *test)
|
||||
{
|
||||
struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL);
|
||||
u32 i;
|
||||
|
||||
r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL);
|
||||
r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(p_avail_data); i++) {
|
||||
r->buffer_size = p_avail_data[i].buffer_size;
|
||||
r->boundary = calculate_boundary(r->buffer_size);
|
||||
r->status->hw_ptr = p_avail_data[i].hw_ptr;
|
||||
r->control->appl_ptr = p_avail_data[i].appl_ptr;
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_playback_avail(r), p_avail_data[i].expected_avail);
|
||||
}
|
||||
}
|
||||
|
||||
static struct avail_test_data c_avail_data[] = {
|
||||
/* hw_ptr - appl_ptr < 0 => avail = hw_ptr - appl_ptr + boundary */
|
||||
{ 128, 1000, 1001, 1073741824UL - 1 },
|
||||
/* standard case: avail = hw_ptr - appl_ptr */
|
||||
{ 128, 1001, 1000, 1 },
|
||||
};
|
||||
|
||||
static void test_capture_avail(struct kunit *test)
|
||||
{
|
||||
struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL);
|
||||
u32 i;
|
||||
|
||||
r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL);
|
||||
r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(c_avail_data); i++) {
|
||||
r->buffer_size = c_avail_data[i].buffer_size;
|
||||
r->boundary = calculate_boundary(r->buffer_size);
|
||||
r->status->hw_ptr = c_avail_data[i].hw_ptr;
|
||||
r->control->appl_ptr = c_avail_data[i].appl_ptr;
|
||||
KUNIT_EXPECT_EQ(test, snd_pcm_capture_avail(r), c_avail_data[i].expected_avail);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_card_set_id(struct kunit *test)
|
||||
{
|
||||
struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL);
|
||||
|
||||
snd_card_set_id(card, VALID_NAME);
|
||||
KUNIT_EXPECT_STREQ(test, card->id, VALID_NAME);
|
||||
|
||||
/* clear the first id character so we can set it again */
|
||||
card->id[0] = '\0';
|
||||
snd_card_set_id(card, NAME_W_SPEC_CHARS);
|
||||
KUNIT_EXPECT_STRNEQ(test, card->id, NAME_W_SPEC_CHARS);
|
||||
|
||||
card->id[0] = '\0';
|
||||
snd_card_set_id(card, NAME_W_SPACE);
|
||||
kunit_info(test, "%s", card->id);
|
||||
KUNIT_EXPECT_STREQ(test, card->id, NAME_W_SPACE_REMOVED);
|
||||
}
|
||||
|
||||
static void test_pcm_format_name(struct kunit *test)
|
||||
{
|
||||
u32 i;
|
||||
const char *name;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_fmt); i++) {
|
||||
name = snd_pcm_format_name(valid_fmt[i].format);
|
||||
KUNIT_ASSERT_NOT_NULL_MSG(test, name, "Don't have name for %s", valid_fmt[i].name);
|
||||
KUNIT_EXPECT_STREQ(test, name, valid_fmt[i].name);
|
||||
}
|
||||
|
||||
KUNIT_ASSERT_STREQ(test, snd_pcm_format_name(WRONG_FORMAT), "Unknown");
|
||||
KUNIT_ASSERT_STREQ(test, snd_pcm_format_name(-1), "Unknown");
|
||||
}
|
||||
|
||||
static void test_card_add_component(struct kunit *test)
|
||||
{
|
||||
struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL);
|
||||
|
||||
snd_component_add(card, TEST_FIRST_COMPONENT);
|
||||
KUNIT_ASSERT_STREQ(test, card->components, TEST_FIRST_COMPONENT);
|
||||
|
||||
snd_component_add(card, TEST_SECOND_COMPONENT);
|
||||
KUNIT_ASSERT_STREQ(test, card->components, TEST_FIRST_COMPONENT " " TEST_SECOND_COMPONENT);
|
||||
}
|
||||
|
||||
static struct kunit_case sound_utils_cases[] = {
|
||||
KUNIT_CASE(test_phys_format_size),
|
||||
KUNIT_CASE(test_format_width),
|
||||
KUNIT_CASE(test_format_endianness),
|
||||
KUNIT_CASE(test_format_signed),
|
||||
KUNIT_CASE(test_format_fill_silence),
|
||||
KUNIT_CASE(test_playback_avail),
|
||||
KUNIT_CASE(test_capture_avail),
|
||||
KUNIT_CASE(test_card_set_id),
|
||||
KUNIT_CASE(test_pcm_format_name),
|
||||
KUNIT_CASE(test_card_add_component),
|
||||
{},
|
||||
};
|
||||
|
||||
static struct kunit_suite sound_utils_suite = {
|
||||
.name = "sound-core-test",
|
||||
.test_cases = sound_utils_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(sound_utils_suite);
|
||||
MODULE_AUTHOR("Ivan Orlov");
|
||||
MODULE_LICENSE("GPL");
|
@ -87,6 +87,8 @@ static const struct cs35l41_config cs35l41_config_table[] = {
|
||||
{ "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
|
||||
{ "10431683", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "104316A3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
@ -468,6 +470,8 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
|
||||
{ "CSC3551", "10431533", generic_dsd_config },
|
||||
{ "CSC3551", "10431573", generic_dsd_config },
|
||||
{ "CSC3551", "10431663", generic_dsd_config },
|
||||
{ "CSC3551", "10431683", generic_dsd_config },
|
||||
{ "CSC3551", "104316A3", generic_dsd_config },
|
||||
{ "CSC3551", "104316D3", generic_dsd_config },
|
||||
{ "CSC3551", "104316F3", generic_dsd_config },
|
||||
{ "CSC3551", "104317F3", generic_dsd_config },
|
||||
|
@ -1729,9 +1729,11 @@ static int default_bdl_pos_adj(struct azx *chip)
|
||||
/* some exceptions: Atoms seem problematic with value 1 */
|
||||
if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
switch (chip->pci->device) {
|
||||
case 0x0f04: /* Baytrail */
|
||||
case 0x2284: /* Braswell */
|
||||
case PCI_DEVICE_ID_INTEL_HDA_BYT:
|
||||
case PCI_DEVICE_ID_INTEL_HDA_BSW:
|
||||
return 32;
|
||||
case PCI_DEVICE_ID_INTEL_HDA_APL:
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1371,6 +1371,7 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac
|
||||
spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1;
|
||||
spec->scodecs[CS8409_CODEC1]->codec = codec;
|
||||
spec->num_scodecs = 2;
|
||||
spec->gen.suppress_vmaster = 1;
|
||||
|
||||
codec->patch_ops = cs8409_dolphin_patch_ops;
|
||||
|
||||
|
@ -438,6 +438,10 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
||||
alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
|
||||
fallthrough;
|
||||
case 0x10ec0215:
|
||||
case 0x10ec0285:
|
||||
case 0x10ec0289:
|
||||
alc_update_coef_idx(codec, 0x36, 1<<13, 0);
|
||||
fallthrough;
|
||||
case 0x10ec0230:
|
||||
case 0x10ec0233:
|
||||
case 0x10ec0235:
|
||||
@ -451,9 +455,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
||||
case 0x10ec0283:
|
||||
case 0x10ec0286:
|
||||
case 0x10ec0288:
|
||||
case 0x10ec0285:
|
||||
case 0x10ec0298:
|
||||
case 0x10ec0289:
|
||||
case 0x10ec0300:
|
||||
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
|
||||
break;
|
||||
@ -9499,6 +9501,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
|
||||
SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1269, "Acer SWIFT SF314-54", ALC256_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x126a, "Acer Swift SF114-32", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
|
||||
@ -9578,6 +9581,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
@ -9698,6 +9702,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8786, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8787, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
||||
|
@ -261,6 +261,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
|
||||
int ret, i, cur, err, pins, clock_id;
|
||||
const u8 *sources;
|
||||
int proto = fmt->protocol;
|
||||
bool readable, writeable;
|
||||
u32 bmControls;
|
||||
|
||||
entity_id &= 0xff;
|
||||
|
||||
@ -292,11 +294,27 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
|
||||
sources = GET_VAL(selector, proto, baCSourceID);
|
||||
cur = 0;
|
||||
|
||||
if (proto == UAC_VERSION_3)
|
||||
bmControls = le32_to_cpu(*(__le32 *)(&selector->v3.baCSourceID[0] + pins));
|
||||
else
|
||||
bmControls = *(__u8 *)(&selector->v2.baCSourceID[0] + pins);
|
||||
|
||||
readable = uac_v2v3_control_is_readable(bmControls,
|
||||
UAC2_CX_CLOCK_SELECTOR);
|
||||
writeable = uac_v2v3_control_is_writeable(bmControls,
|
||||
UAC2_CX_CLOCK_SELECTOR);
|
||||
|
||||
if (pins == 1) {
|
||||
ret = 1;
|
||||
goto find_source;
|
||||
}
|
||||
|
||||
/* for now just warn about buggy device */
|
||||
if (!readable)
|
||||
usb_audio_warn(chip,
|
||||
"%s(): clock selector control is not readable, id %d\n",
|
||||
__func__, clock_id);
|
||||
|
||||
/* the entity ID we are looking at is a selector.
|
||||
* find out what it currently selects */
|
||||
ret = uac_clock_selector_get_val(chip, clock_id);
|
||||
@ -325,7 +343,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
|
||||
visited, validate);
|
||||
if (ret > 0) {
|
||||
/* Skip setting clock selector again for some devices */
|
||||
if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
|
||||
if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR ||
|
||||
!writeable)
|
||||
return ret;
|
||||
err = uac_clock_selector_set_val(chip, entity_id, cur);
|
||||
if (err < 0)
|
||||
@ -336,6 +355,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
|
||||
return ret;
|
||||
|
||||
find_others:
|
||||
if (!writeable)
|
||||
return -ENXIO;
|
||||
|
||||
/* The current clock source is invalid, try others. */
|
||||
for (i = 1; i <= pins; i++) {
|
||||
if (i == cur)
|
||||
|
@ -470,9 +470,11 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
|
||||
int clock)
|
||||
{
|
||||
struct usb_device *dev = chip->dev;
|
||||
struct usb_host_interface *alts;
|
||||
unsigned int *table;
|
||||
unsigned int nr_rates;
|
||||
int i, err;
|
||||
u32 bmControls;
|
||||
|
||||
/* performing the rate verification may lead to unexpected USB bus
|
||||
* behavior afterwards by some unknown reason. Do this only for the
|
||||
@ -481,6 +483,24 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
|
||||
if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES))
|
||||
return 0; /* don't perform the validation as default */
|
||||
|
||||
alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting);
|
||||
if (!alts)
|
||||
return 0;
|
||||
|
||||
if (fp->protocol == UAC_VERSION_3) {
|
||||
struct uac3_as_header_descriptor *as = snd_usb_find_csint_desc(
|
||||
alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
|
||||
bmControls = le32_to_cpu(as->bmControls);
|
||||
} else {
|
||||
struct uac2_as_header_descriptor *as = snd_usb_find_csint_desc(
|
||||
alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
|
||||
bmControls = as->bmControls;
|
||||
}
|
||||
|
||||
if (!uac_v2v3_control_is_readable(bmControls,
|
||||
UAC2_AS_VAL_ALT_SETTINGS))
|
||||
return 0;
|
||||
|
||||
table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
|
@ -1085,7 +1085,7 @@ int snd_usb_midi_v2_create(struct snd_usb_audio *chip,
|
||||
}
|
||||
if ((quirk && quirk->type != QUIRK_MIDI_STANDARD_INTERFACE) ||
|
||||
iface->num_altsetting < 2) {
|
||||
usb_audio_info(chip, "Quirk or no altest; falling back to MIDI 1.0\n");
|
||||
usb_audio_info(chip, "Quirk or no altset; falling back to MIDI 1.0\n");
|
||||
goto fallback_to_midi1;
|
||||
}
|
||||
hostif = &iface->altsetting[1];
|
||||
|
@ -2031,10 +2031,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
||||
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
|
||||
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */
|
||||
QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M),
|
||||
DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
|
||||
QUIRK_FLAG_IFACE_SKIP_CLOSE),
|
||||
DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */
|
||||
QUIRK_FLAG_SET_IFACE_FIRST),
|
||||
DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */
|
||||
@ -2073,14 +2077,22 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x0763, 0x2031, /* M-Audio Fast Track C600 */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x07fd, 0x000b, /* MOTU M Series 2nd hardware revision */
|
||||
QUIRK_FLAG_CTL_MSG_DELAY_1M),
|
||||
DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
|
||||
QUIRK_FLAG_IGNORE_CTL_ERROR),
|
||||
DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */
|
||||
QUIRK_FLAG_CTL_MSG_DELAY_1M),
|
||||
DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */
|
||||
QUIRK_FLAG_CTL_MSG_DELAY_1M),
|
||||
DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
|
||||
QUIRK_FLAG_FIXED_RATE),
|
||||
DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
|
||||
QUIRK_FLAG_FIXED_RATE),
|
||||
DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
|
||||
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
|
||||
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
|
||||
@ -2113,6 +2125,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
||||
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
|
||||
DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
|
||||
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
|
||||
DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
|
||||
@ -2155,6 +2171,12 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
||||
QUIRK_FLAG_IGNORE_CTL_ERROR),
|
||||
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
|
||||
QUIRK_FLAG_IGNORE_CTL_ERROR),
|
||||
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
|
||||
@ -2163,22 +2185,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
||||
QUIRK_FLAG_ALIGN_TRANSFER),
|
||||
DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
|
||||
QUIRK_FLAG_ALIGN_TRANSFER),
|
||||
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
|
||||
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
|
||||
DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
|
||||
QUIRK_FLAG_IFACE_SKIP_CLOSE),
|
||||
DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
|
||||
QUIRK_FLAG_FIXED_RATE),
|
||||
DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
|
||||
QUIRK_FLAG_FIXED_RATE),
|
||||
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
|
||||
QUIRK_FLAG_GET_SAMPLE_RATE),
|
||||
|
||||
/* Vendor matches */
|
||||
VENDOR_FLG(0x045e, /* MS Lifecam */
|
||||
|
@ -91,8 +91,6 @@ static void virtsnd_event_notify_cb(struct virtqueue *vqueue)
|
||||
virtsnd_event_dispatch(snd, event);
|
||||
virtsnd_event_send(vqueue, event, true, GFP_ATOMIC);
|
||||
}
|
||||
if (unlikely(virtqueue_is_broken(vqueue)))
|
||||
break;
|
||||
} while (!virtqueue_enable_cb(vqueue));
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
}
|
||||
|
@ -303,8 +303,6 @@ void virtsnd_ctl_notify_cb(struct virtqueue *vqueue)
|
||||
virtqueue_disable_cb(vqueue);
|
||||
while ((msg = virtqueue_get_buf(vqueue, &length)))
|
||||
virtsnd_ctl_msg_complete(msg);
|
||||
if (unlikely(virtqueue_is_broken(vqueue)))
|
||||
break;
|
||||
} while (!virtqueue_enable_cb(vqueue));
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
}
|
||||
|
@ -358,8 +358,6 @@ static inline void virtsnd_pcm_notify_cb(struct virtio_snd_queue *queue)
|
||||
virtqueue_disable_cb(queue->vqueue);
|
||||
while ((msg = virtqueue_get_buf(queue->vqueue, &written_bytes)))
|
||||
virtsnd_pcm_msg_complete(msg, written_bytes);
|
||||
if (unlikely(virtqueue_is_broken(queue->vqueue)))
|
||||
break;
|
||||
} while (!virtqueue_enable_cb(queue->vqueue));
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user