Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/qcom/mixer_usb_offload.c
26426 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
4
*/
5
6
#include <linux/usb.h>
7
8
#include <sound/core.h>
9
#include <sound/control.h>
10
#include <sound/soc-usb.h>
11
12
#include "../usbaudio.h"
13
#include "../card.h"
14
#include "../helper.h"
15
#include "../mixer.h"
16
17
#include "mixer_usb_offload.h"
18
19
#define PCM_IDX(n) ((n) & 0xffff)
20
#define CARD_IDX(n) ((n) >> 16)
21
22
static int
23
snd_usb_offload_card_route_get(struct snd_kcontrol *kcontrol,
24
struct snd_ctl_elem_value *ucontrol)
25
{
26
struct device *sysdev = snd_kcontrol_chip(kcontrol);
27
int ret;
28
29
ret = snd_soc_usb_update_offload_route(sysdev,
30
CARD_IDX(kcontrol->private_value),
31
PCM_IDX(kcontrol->private_value),
32
SNDRV_PCM_STREAM_PLAYBACK,
33
SND_SOC_USB_KCTL_CARD_ROUTE,
34
ucontrol->value.integer.value);
35
if (ret < 0) {
36
ucontrol->value.integer.value[0] = -1;
37
ucontrol->value.integer.value[1] = -1;
38
}
39
40
return 0;
41
}
42
43
static int snd_usb_offload_card_route_info(struct snd_kcontrol *kcontrol,
44
struct snd_ctl_elem_info *uinfo)
45
{
46
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
47
uinfo->count = 1;
48
uinfo->value.integer.min = -1;
49
uinfo->value.integer.max = SNDRV_CARDS;
50
51
return 0;
52
}
53
54
static struct snd_kcontrol_new snd_usb_offload_mapped_card_ctl = {
55
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
56
.access = SNDRV_CTL_ELEM_ACCESS_READ,
57
.info = snd_usb_offload_card_route_info,
58
.get = snd_usb_offload_card_route_get,
59
};
60
61
static int
62
snd_usb_offload_pcm_route_get(struct snd_kcontrol *kcontrol,
63
struct snd_ctl_elem_value *ucontrol)
64
{
65
struct device *sysdev = snd_kcontrol_chip(kcontrol);
66
int ret;
67
68
ret = snd_soc_usb_update_offload_route(sysdev,
69
CARD_IDX(kcontrol->private_value),
70
PCM_IDX(kcontrol->private_value),
71
SNDRV_PCM_STREAM_PLAYBACK,
72
SND_SOC_USB_KCTL_PCM_ROUTE,
73
ucontrol->value.integer.value);
74
if (ret < 0) {
75
ucontrol->value.integer.value[0] = -1;
76
ucontrol->value.integer.value[1] = -1;
77
}
78
79
return 0;
80
}
81
82
static int snd_usb_offload_pcm_route_info(struct snd_kcontrol *kcontrol,
83
struct snd_ctl_elem_info *uinfo)
84
{
85
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
86
uinfo->count = 1;
87
uinfo->value.integer.min = -1;
88
/* Arbitrary max value, as there is no 'limit' on number of PCM devices */
89
uinfo->value.integer.max = 0xff;
90
91
return 0;
92
}
93
94
static struct snd_kcontrol_new snd_usb_offload_mapped_pcm_ctl = {
95
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
96
.access = SNDRV_CTL_ELEM_ACCESS_READ,
97
.info = snd_usb_offload_pcm_route_info,
98
.get = snd_usb_offload_pcm_route_get,
99
};
100
101
/**
102
* snd_usb_offload_create_ctl() - Add USB offload bounded mixer
103
* @chip: USB SND chip device
104
* @bedev: Reference to USB backend DAI device
105
*
106
* Creates a sound control for a USB audio device, so that applications can
107
* query for if there is an available USB audio offload path, and which
108
* card is managing it.
109
*/
110
int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev)
111
{
112
struct snd_kcontrol_new *chip_kctl;
113
struct snd_usb_substream *subs;
114
struct snd_usb_stream *as;
115
char ctl_name[48];
116
int ret;
117
118
list_for_each_entry(as, &chip->pcm_list, list) {
119
subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK];
120
if (!subs->ep_num || as->pcm_index > 0xff)
121
continue;
122
123
chip_kctl = &snd_usb_offload_mapped_card_ctl;
124
chip_kctl->count = 1;
125
/*
126
* Store the associated USB SND card number and PCM index for
127
* the kctl.
128
*/
129
chip_kctl->private_value = as->pcm_index |
130
chip->card->number << 16;
131
sprintf(ctl_name, "USB Offload Playback Card Route PCM#%d",
132
as->pcm_index);
133
chip_kctl->name = ctl_name;
134
ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
135
if (ret < 0)
136
break;
137
138
chip_kctl = &snd_usb_offload_mapped_pcm_ctl;
139
chip_kctl->count = 1;
140
/*
141
* Store the associated USB SND card number and PCM index for
142
* the kctl.
143
*/
144
chip_kctl->private_value = as->pcm_index |
145
chip->card->number << 16;
146
sprintf(ctl_name, "USB Offload Playback PCM Route PCM#%d",
147
as->pcm_index);
148
chip_kctl->name = ctl_name;
149
ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
150
if (ret < 0)
151
break;
152
}
153
154
return ret;
155
}
156
157