1#ifndef fooalsaucmhfoo
2#define fooalsaucmhfoo
3
4/***
5  This file is part of PulseAudio.
6
7  Copyright 2011 Wolfson Microelectronics PLC
8  Author Margarita Olaya <magi@slimlogic.co.uk>
9  Copyright 2012 Feng Wei <wei.feng@freescale.com>, Freescale Ltd.
10
11  PulseAudio is free software; you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published
13  by the Free Software Foundation; either version 2.1 of the License,
14  or (at your option) any later version.
15
16  PulseAudio is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU Lesser General Public License
22  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
23***/
24
25#ifdef HAVE_ALSA_UCM
26#include <alsa/use-case.h>
27#else
28typedef void snd_use_case_mgr_t;
29#endif
30
31#include "alsa-mixer.h"
32
33/** For devices: List of verbs, devices or modifiers available */
34#define PA_ALSA_PROP_UCM_NAME                       "alsa.ucm.name"
35
36/** For devices: List of supported devices per verb*/
37#define PA_ALSA_PROP_UCM_DESCRIPTION                "alsa.ucm.description"
38
39/** For devices: Playback device name e.g PlaybackPCM */
40#define PA_ALSA_PROP_UCM_SINK                       "alsa.ucm.sink"
41
42/** For devices: Capture device name e.g CapturePCM*/
43#define PA_ALSA_PROP_UCM_SOURCE                     "alsa.ucm.source"
44
45/** For devices: Playback roles */
46#define PA_ALSA_PROP_UCM_PLAYBACK_ROLES             "alsa.ucm.playback.roles"
47
48/** For devices: Playback control device name  */
49#define PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE        "alsa.ucm.playback.ctldev"
50
51/** For devices: Playback control volume ID string. e.g PlaybackVolume */
52#define PA_ALSA_PROP_UCM_PLAYBACK_VOLUME            "alsa.ucm.playback.volume"
53
54/** For devices: Playback switch e.g PlaybackSwitch */
55#define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH            "alsa.ucm.playback.switch"
56
57/** For devices: Playback mixer device name  */
58#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE      "alsa.ucm.playback.mixer.device"
59
60/** For devices: Playback mixer identifier */
61#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM        "alsa.ucm.playback.mixer.element"
62
63/** For devices: Playback mixer master identifier */
64#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM       "alsa.ucm.playback.master.element"
65
66/** For devices: Playback mixer master type */
67#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE       "alsa.ucm.playback.master.type"
68
69/** For devices: Playback mixer master identifier */
70#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID         "alsa.ucm.playback.master.id"
71
72/** For devices: Playback mixer master type */
73#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE       "alsa.ucm.playback.master.type"
74
75/** For devices: Playback priority */
76#define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY          "alsa.ucm.playback.priority"
77
78/** For devices: Playback rate */
79#define PA_ALSA_PROP_UCM_PLAYBACK_RATE              "alsa.ucm.playback.rate"
80
81/** For devices: Playback channels */
82#define PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS          "alsa.ucm.playback.channels"
83
84/** For devices: Capture roles */
85#define PA_ALSA_PROP_UCM_CAPTURE_ROLES              "alsa.ucm.capture.roles"
86
87/** For devices: Capture control device name  */
88#define PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE         "alsa.ucm.capture.ctldev"
89
90/** For devices: Capture controls volume ID string. e.g CaptureVolume */
91#define PA_ALSA_PROP_UCM_CAPTURE_VOLUME             "alsa.ucm.capture.volume"
92
93/** For devices: Capture switch e.g CaptureSwitch */
94#define PA_ALSA_PROP_UCM_CAPTURE_SWITCH             "alsa.ucm.capture.switch"
95
96/** For devices: Capture mixer device name  */
97#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE       "alsa.ucm.capture.mixer.device"
98
99/** For devices: Capture mixer identifier */
100#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM         "alsa.ucm.capture.mixer.element"
101
102/** For devices: Capture mixer identifier */
103#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM        "alsa.ucm.capture.master.element"
104
105/** For devices: Capture mixer identifier */
106#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE        "alsa.ucm.capture.master.type"
107
108/** For devices: Capture mixer identifier */
109#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID          "alsa.ucm.capture.master.id"
110
111/** For devices: Capture mixer identifier */
112#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE        "alsa.ucm.capture.master.type"
113
114/** For devices: Capture priority */
115#define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY           "alsa.ucm.capture.priority"
116
117/** For devices: Capture rate */
118#define PA_ALSA_PROP_UCM_CAPTURE_RATE               "alsa.ucm.capture.rate"
119
120/** For devices: Capture channels */
121#define PA_ALSA_PROP_UCM_CAPTURE_CHANNELS           "alsa.ucm.capture.channels"
122
123/** For devices: Quality of Service */
124#define PA_ALSA_PROP_UCM_QOS                        "alsa.ucm.qos"
125
126/** For devices: The modifier (if any) that this device corresponds to */
127#define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier"
128
129/* Corresponds to the "JackCTL" UCM value. */
130#define PA_ALSA_PROP_UCM_JACK_DEVICE		    "alsa.ucm.jack_device"
131
132/* Corresponds to the "JackControl" UCM value. */
133#define PA_ALSA_PROP_UCM_JACK_CONTROL               "alsa.ucm.jack_control"
134
135/* Corresponds to the "JackHWMute" UCM value. */
136#define PA_ALSA_PROP_UCM_JACK_HW_MUTE               "alsa.ucm.jack_hw_mute"
137
138typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
139typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
140typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
141typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
142typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
143typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
144typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
145
146int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
147pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
148int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile);
149
150int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb);
151
152void pa_alsa_ucm_add_ports(
153        pa_hashmap **hash,
154        pa_proplist *proplist,
155        pa_alsa_ucm_mapping_context *context,
156        bool is_sink,
157        pa_card *card,
158        snd_pcm_t *pcm_handle,
159        bool ignore_dB);
160void pa_alsa_ucm_add_ports_combination(
161        pa_hashmap *hash,
162        pa_alsa_ucm_mapping_context *context,
163        bool is_sink,
164        pa_hashmap *ports,
165        pa_card_profile *cp,
166        pa_core *core);
167int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, bool is_sink);
168
169void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm);
170void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
171
172void pa_alsa_ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
173void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
174
175/* UCM - Use Case Manager is available on some audio cards */
176
177struct pa_alsa_ucm_device {
178    PA_LLIST_FIELDS(pa_alsa_ucm_device);
179
180    pa_proplist *proplist;
181
182    pa_device_port_type_t type;
183
184    unsigned playback_priority;
185    unsigned capture_priority;
186
187    unsigned playback_rate;
188    unsigned capture_rate;
189
190    unsigned playback_channels;
191    unsigned capture_channels;
192
193    /* These may be different per verb, so we store this as a hashmap of verb -> volume_control. We might eventually want to
194     * make this a hashmap of verb -> per-verb-device-properties-struct. */
195    pa_hashmap *playback_volumes;
196    pa_hashmap *capture_volumes;
197
198    pa_alsa_mapping *playback_mapping;
199    pa_alsa_mapping *capture_mapping;
200
201    pa_idxset *conflicting_devices;
202    pa_idxset *supported_devices;
203
204    /* One device may be part of multiple ports, since each device has
205     * a dedicated port, and in addition to that we sometimes generate ports
206     * that represent combinations of devices. */
207    pa_dynarray *ucm_ports; /* struct ucm_port */
208
209    pa_alsa_jack *jack;
210    pa_dynarray *hw_mute_jacks; /* pa_alsa_jack */
211    pa_available_t available;
212
213    char *eld_mixer_device_name;
214    int eld_device;
215};
216
217void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device);
218
219struct pa_alsa_ucm_modifier {
220    PA_LLIST_FIELDS(pa_alsa_ucm_modifier);
221
222    pa_proplist *proplist;
223
224    int n_confdev;
225    int n_suppdev;
226
227    const char **conflicting_devices;
228    const char **supported_devices;
229
230    pa_direction_t action_direction;
231
232    char *media_role;
233
234    /* Non-NULL if the modifier has its own PlaybackPCM/CapturePCM */
235    pa_alsa_mapping *playback_mapping;
236    pa_alsa_mapping *capture_mapping;
237
238    /* Count how many role matched streams are running */
239    int enabled_counter;
240};
241
242struct pa_alsa_ucm_verb {
243    PA_LLIST_FIELDS(pa_alsa_ucm_verb);
244
245    pa_proplist *proplist;
246    unsigned priority;
247
248    PA_LLIST_HEAD(pa_alsa_ucm_device, devices);
249    PA_LLIST_HEAD(pa_alsa_ucm_modifier, modifiers);
250};
251
252struct pa_alsa_ucm_config {
253    pa_core *core;
254    snd_use_case_mgr_t *ucm_mgr;
255    pa_alsa_ucm_verb *active_verb;
256    char *alib_prefix;
257
258    pa_hashmap *mixers;
259    PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
260    PA_LLIST_HEAD(pa_alsa_jack, jacks);
261};
262
263struct pa_alsa_ucm_mapping_context {
264    pa_alsa_ucm_config *ucm;
265    pa_direction_t direction;
266
267    pa_idxset *ucm_devices;
268    pa_idxset *ucm_modifiers;
269};
270
271struct pa_alsa_ucm_port_data {
272    pa_alsa_ucm_config *ucm;
273    pa_device_port *core_port;
274
275    /* A single port will be associated with multiple devices if it represents
276     * a combination of devices. */
277    pa_dynarray *devices; /* pa_alsa_ucm_device */
278
279    /* profile name -> pa_alsa_path for volume control */
280    pa_hashmap *paths;
281    /* Current path, set when activating profile */
282    pa_alsa_path *path;
283
284    /* ELD info */
285    char *eld_mixer_device_name;
286    int eld_device; /* PCM device number */
287};
288
289struct pa_alsa_ucm_volume {
290    char *mixer_elem;	/* mixer element identifier */
291    char *master_elem;	/* master mixer element identifier */
292    char *master_type;
293};
294
295#endif
296