Skip to content

Commit 16ea997

Browse files
committed
Merge remote-tracking branch 'takashi/for-next' into sound/upstream-20260313
2 parents 8aa902d + 103a7b9 commit 16ea997

20 files changed

Lines changed: 477 additions & 65 deletions

File tree

Documentation/sound/alsa-configuration.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,6 +2376,13 @@ quirk_flags
23762376
Skip the probe-time interface setup (usb_set_interface,
23772377
init_pitch, init_sample_rate); redundant with
23782378
snd_usb_endpoint_prepare() at stream-open time
2379+
* bit 27: ``mixer_playback_linear_vol``
2380+
Set linear volume mapping for devices where the playback volume
2381+
control value is mapped to voltage (instead of dB) level linearly.
2382+
In short: ``x(raw) = (raw - raw_min) / (raw_max - raw_min)``;
2383+
``V(x) = k * x``; ``dB(x) = 20 * log10(x)``. Overrides bit 24
2384+
* bit 28: ``mixer_capture_linear_vol``
2385+
Similar to bit 27 but for capture streams. Overrides bit 25
23792386

23802387
This module supports multiple devices, autoprobe and hotplugging.
23812388

include/sound/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ struct snd_card {
133133
#ifdef CONFIG_SND_DEBUG
134134
struct dentry *debugfs_root; /* debugfs root for card */
135135
#endif
136+
#ifdef CONFIG_SND_CTL_DEBUG
137+
struct snd_ctl_elem_value *value_buf; /* buffer for kctl->put() verification */
138+
#endif
136139

137140
#ifdef CONFIG_PM
138141
unsigned int power_state; /* power state */

sound/aoa/aoa.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct aoa_codec {
4848
u32 connected;
4949

5050
/* data the fabric can associate with this structure */
51-
void *fabric_data;
51+
const void *fabric_data;
5252

5353
/* private! */
5454
struct list_head list;

sound/aoa/fabrics/layout.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct codec_connection {
5555

5656
struct codec_connect_info {
5757
char *name;
58-
struct codec_connection *connections;
58+
const struct codec_connection *connections;
5959
};
6060

6161
#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)
@@ -116,7 +116,7 @@ MODULE_ALIAS("aoa-device-id-35");
116116
MODULE_ALIAS("aoa-device-id-44");
117117

118118
/* onyx with all but microphone connected */
119-
static struct codec_connection onyx_connections_nomic[] = {
119+
static const struct codec_connection onyx_connections_nomic[] = {
120120
{
121121
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
122122
.codec_bit = 0,
@@ -133,7 +133,7 @@ static struct codec_connection onyx_connections_nomic[] = {
133133
};
134134

135135
/* onyx on machines without headphone */
136-
static struct codec_connection onyx_connections_noheadphones[] = {
136+
static const struct codec_connection onyx_connections_noheadphones[] = {
137137
{
138138
.connected = CC_SPEAKERS | CC_LINEOUT |
139139
CC_LINEOUT_LABELLED_HEADPHONE,
@@ -157,7 +157,7 @@ static struct codec_connection onyx_connections_noheadphones[] = {
157157
};
158158

159159
/* onyx on machines with real line-out */
160-
static struct codec_connection onyx_connections_reallineout[] = {
160+
static const struct codec_connection onyx_connections_reallineout[] = {
161161
{
162162
.connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
163163
.codec_bit = 0,
@@ -174,7 +174,7 @@ static struct codec_connection onyx_connections_reallineout[] = {
174174
};
175175

176176
/* tas on machines without line out */
177-
static struct codec_connection tas_connections_nolineout[] = {
177+
static const struct codec_connection tas_connections_nolineout[] = {
178178
{
179179
.connected = CC_SPEAKERS | CC_HEADPHONE,
180180
.codec_bit = 0,
@@ -191,7 +191,7 @@ static struct codec_connection tas_connections_nolineout[] = {
191191
};
192192

193193
/* tas on machines with neither line out nor line in */
194-
static struct codec_connection tas_connections_noline[] = {
194+
static const struct codec_connection tas_connections_noline[] = {
195195
{
196196
.connected = CC_SPEAKERS | CC_HEADPHONE,
197197
.codec_bit = 0,
@@ -204,7 +204,7 @@ static struct codec_connection tas_connections_noline[] = {
204204
};
205205

206206
/* tas on machines without microphone */
207-
static struct codec_connection tas_connections_nomic[] = {
207+
static const struct codec_connection tas_connections_nomic[] = {
208208
{
209209
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
210210
.codec_bit = 0,
@@ -217,7 +217,7 @@ static struct codec_connection tas_connections_nomic[] = {
217217
};
218218

219219
/* tas on machines with everything connected */
220-
static struct codec_connection tas_connections_all[] = {
220+
static const struct codec_connection tas_connections_all[] = {
221221
{
222222
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
223223
.codec_bit = 0,
@@ -233,31 +233,31 @@ static struct codec_connection tas_connections_all[] = {
233233
{} /* terminate array by .connected == 0 */
234234
};
235235

236-
static struct codec_connection toonie_connections[] = {
236+
static const struct codec_connection toonie_connections[] = {
237237
{
238238
.connected = CC_SPEAKERS | CC_HEADPHONE,
239239
.codec_bit = 0,
240240
},
241241
{} /* terminate array by .connected == 0 */
242242
};
243243

244-
static struct codec_connection topaz_input[] = {
244+
static const struct codec_connection topaz_input[] = {
245245
{
246246
.connected = CC_DIGITALIN,
247247
.codec_bit = 0,
248248
},
249249
{} /* terminate array by .connected == 0 */
250250
};
251251

252-
static struct codec_connection topaz_output[] = {
252+
static const struct codec_connection topaz_output[] = {
253253
{
254254
.connected = CC_DIGITALOUT,
255255
.codec_bit = 1,
256256
},
257257
{} /* terminate array by .connected == 0 */
258258
};
259259

260-
static struct codec_connection topaz_inout[] = {
260+
static const struct codec_connection topaz_inout[] = {
261261
{
262262
.connected = CC_DIGITALIN,
263263
.codec_bit = 0,
@@ -772,7 +772,7 @@ static int check_codec(struct aoa_codec *codec,
772772
{
773773
const u32 *ref;
774774
char propname[32];
775-
struct codec_connection *cc;
775+
const struct codec_connection *cc;
776776

777777
/* if the codec has a 'codec' node, we require a reference */
778778
if (of_node_name_eq(codec->node, "codec")) {
@@ -895,7 +895,7 @@ static void layout_notify(void *data)
895895

896896
static void layout_attached_codec(struct aoa_codec *codec)
897897
{
898-
struct codec_connection *cc;
898+
const struct codec_connection *cc;
899899
struct snd_kcontrol *ctl;
900900
int headphones, lineout;
901901
struct layout_dev *ldev = layout_device;

sound/aoa/soundbus/i2sbus/core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ static int i2sbus_resume(struct macio_dev* dev)
405405
int err, ret = 0;
406406

407407
list_for_each_entry(i2sdev, &control->list, item) {
408+
if (list_empty(&i2sdev->sound.codec_list))
409+
continue;
410+
408411
/* reset i2s bus format etc. */
409412
i2sbus_pcm_prepare_both(i2sdev);
410413

sound/aoa/soundbus/i2sbus/pcm.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,17 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
383383
/* set stop command */
384384
command->command = cpu_to_le16(DBDMA_STOP);
385385

386+
cii = list_first_entry(&i2sdev->sound.codec_list,
387+
struct codec_info_item, list);
388+
386389
/* ok, let's set the serial format and stuff */
387390
switch (runtime->format) {
388391
/* 16 bit formats */
389392
case SNDRV_PCM_FORMAT_S16_BE:
390393
case SNDRV_PCM_FORMAT_U16_BE:
391394
/* FIXME: if we add different bus factors we need to
392395
* do more here!! */
393-
bi.bus_factor = 0;
394-
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
395-
bi.bus_factor = cii->codec->bus_factor;
396-
break;
397-
}
398-
if (!bi.bus_factor)
399-
return -ENODEV;
396+
bi.bus_factor = cii->codec->bus_factor;
400397
input_16bit = 1;
401398
break;
402399
case SNDRV_PCM_FORMAT_S32_BE:
@@ -410,10 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
410407
return -EINVAL;
411408
}
412409
/* we assume all sysclocks are the same! */
413-
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
414-
bi.sysclock_factor = cii->codec->sysclock_factor;
415-
break;
416-
}
410+
bi.sysclock_factor = cii->codec->sysclock_factor;
417411

418412
if (clock_and_divisors(bi.sysclock_factor,
419413
bi.bus_factor,

sound/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
2323
# for trace-points
2424
CFLAGS_pcm_lib.o := -I$(src)
2525
CFLAGS_pcm_native.o := -I$(src)
26+
CFLAGS_control.o := -I$(src)
2627

2728
snd-pcm-dmaengine-y := pcm_dmaengine.o
2829

sound/core/control.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
#include <sound/info.h>
2020
#include <sound/control.h>
2121

22+
#ifdef CONFIG_SND_CTL_DEBUG
23+
#define CREATE_TRACE_POINTS
24+
#include "control_trace.h"
25+
#else
26+
#define trace_snd_ctl_put(card, kctl, iname, expected, actual)
27+
#endif
28+
2229
// Max allocation size for user controls.
2330
static int max_user_ctl_alloc_size = 8 * 1024 * 1024;
2431
module_param_named(max_user_ctl_alloc_size, max_user_ctl_alloc_size, int, 0444);
@@ -1264,6 +1271,72 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
12641271
return result;
12651272
}
12661273

1274+
#if IS_ENABLED(CONFIG_SND_CTL_DEBUG)
1275+
1276+
static const char *const snd_ctl_elem_iface_names[] = {
1277+
[SNDRV_CTL_ELEM_IFACE_CARD] = "CARD",
1278+
[SNDRV_CTL_ELEM_IFACE_HWDEP] = "HWDEP",
1279+
[SNDRV_CTL_ELEM_IFACE_MIXER] = "MIXER",
1280+
[SNDRV_CTL_ELEM_IFACE_PCM] = "PCM",
1281+
[SNDRV_CTL_ELEM_IFACE_RAWMIDI] = "RAWMIDI",
1282+
[SNDRV_CTL_ELEM_IFACE_TIMER] = "TIMER",
1283+
[SNDRV_CTL_ELEM_IFACE_SEQUENCER] = "SEQUENCER",
1284+
};
1285+
1286+
static int snd_ctl_put_verify(struct snd_card *card, struct snd_kcontrol *kctl,
1287+
struct snd_ctl_elem_value *control)
1288+
{
1289+
struct snd_ctl_elem_value *original = card->value_buf;
1290+
struct snd_ctl_elem_info info;
1291+
const char *iname;
1292+
int ret, retcmp;
1293+
1294+
memset(original, 0, sizeof(*original));
1295+
memset(&info, 0, sizeof(info));
1296+
1297+
ret = kctl->info(kctl, &info);
1298+
if (ret)
1299+
return ret;
1300+
1301+
ret = kctl->get(kctl, original);
1302+
if (ret)
1303+
return ret;
1304+
1305+
ret = kctl->put(kctl, control);
1306+
if (ret < 0)
1307+
return ret;
1308+
1309+
/* Sanitize the new value (control->value) before comparing. */
1310+
fill_remaining_elem_value(control, &info, 0);
1311+
1312+
/* With known state for both new and original, do the comparison. */
1313+
retcmp = memcmp(&original->value, &control->value, sizeof(original->value));
1314+
if (retcmp)
1315+
retcmp = 1;
1316+
1317+
iname = snd_ctl_elem_iface_names[kctl->id.iface];
1318+
trace_snd_ctl_put(&kctl->id, iname, card->number, ret, retcmp);
1319+
1320+
return ret;
1321+
}
1322+
1323+
static int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
1324+
struct snd_ctl_elem_value *control, unsigned int access)
1325+
{
1326+
if ((access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK) ||
1327+
(access & SNDRV_CTL_ELEM_ACCESS_VOLATILE))
1328+
return kctl->put(kctl, control);
1329+
1330+
return snd_ctl_put_verify(card, kctl, control);
1331+
}
1332+
#else
1333+
static inline int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
1334+
struct snd_ctl_elem_value *control, unsigned int access)
1335+
{
1336+
return kctl->put(kctl, control);
1337+
}
1338+
#endif
1339+
12671340
static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
12681341
struct snd_ctl_elem_value *control)
12691342
{
@@ -1300,7 +1373,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
13001373
false);
13011374
}
13021375
if (!result)
1303-
result = kctl->put(kctl, control);
1376+
result = snd_ctl_put(card, kctl, control, vd->access);
1377+
13041378
if (result < 0) {
13051379
up_write(&card->controls_rwsem);
13061380
return result;

sound/core/control_trace.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#undef TRACE_SYSTEM
3+
#define TRACE_SYSTEM snd_ctl
4+
5+
#if !defined(_TRACE_SND_CTL_H) || defined(TRACE_HEADER_MULTI_READ)
6+
#define _TRACE_SND_CTL_H
7+
8+
#include <linux/tracepoint.h>
9+
#include <uapi/sound/asound.h>
10+
11+
TRACE_EVENT(snd_ctl_put,
12+
13+
TP_PROTO(struct snd_ctl_elem_id *id, const char *iname, unsigned int card,
14+
int expected, int actual),
15+
16+
TP_ARGS(id, iname, card, expected, actual),
17+
18+
TP_STRUCT__entry(
19+
__field(unsigned int, numid)
20+
__string(iname, iname)
21+
__string(kname, id->name)
22+
__field(unsigned int, index)
23+
__field(unsigned int, device)
24+
__field(unsigned int, subdevice)
25+
__field(unsigned int, card)
26+
__field(int, expected)
27+
__field(int, actual)
28+
),
29+
30+
TP_fast_assign(
31+
__entry->numid = id->numid;
32+
__assign_str(iname);
33+
__assign_str(kname);
34+
__entry->index = id->index;
35+
__entry->device = id->device;
36+
__entry->subdevice = id->subdevice;
37+
__entry->card = card;
38+
__entry->expected = expected;
39+
__entry->actual = actual;
40+
),
41+
42+
TP_printk("%s: expected=%d, actual=%d for ctl numid=%d, iface=%s, name='%s', index=%d, device=%d, subdevice=%d, card=%d\n",
43+
__entry->expected == __entry->actual ? "success" : "fail",
44+
__entry->expected, __entry->actual, __entry->numid,
45+
__get_str(iname), __get_str(kname), __entry->index,
46+
__entry->device, __entry->subdevice, __entry->card)
47+
);
48+
49+
#endif /* _TRACE_SND_CTL_H */
50+
51+
/* This part must be outside protection */
52+
#undef TRACE_INCLUDE_PATH
53+
#define TRACE_INCLUDE_PATH .
54+
#define TRACE_INCLUDE_FILE control_trace
55+
#include <trace/define_trace.h>

sound/core/init.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
362362
#ifdef CONFIG_SND_DEBUG
363363
card->debugfs_root = debugfs_create_dir(dev_name(&card->card_dev),
364364
sound_debugfs_root);
365+
#endif
366+
#ifdef CONFIG_SND_CTL_DEBUG
367+
card->value_buf = kmalloc(sizeof(*card->value_buf), GFP_KERNEL);
368+
if (!card->value_buf)
369+
return -ENOMEM;
365370
#endif
366371
return 0;
367372

@@ -587,6 +592,9 @@ static int snd_card_do_free(struct snd_card *card)
587592
snd_device_free_all(card);
588593
if (card->private_free)
589594
card->private_free(card);
595+
#ifdef CONFIG_SND_CTL_DEBUG
596+
kfree(card->value_buf);
597+
#endif
590598
if (snd_info_card_free(card) < 0) {
591599
dev_warn(card->dev, "unable to free card info\n");
592600
/* Not fatal error */

0 commit comments

Comments
 (0)