1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0+ */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * u_audio.h -- interface to USB gadget "ALSA sound card" utilities
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016
6*4882a593Smuzhiyun * Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #ifndef __U_AUDIO_H
10*4882a593Smuzhiyun #define __U_AUDIO_H
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/usb/composite.h>
13*4882a593Smuzhiyun #include "uac_common.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * Same maximum frequency deviation on the slower side as in
17*4882a593Smuzhiyun * sound/usb/endpoint.c. Value is expressed in per-mil deviation.
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun #define FBACK_SLOW_MAX 250
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun * Maximum frequency deviation on the faster side, default value for UAC1/2.
23*4882a593Smuzhiyun * Value is expressed in per-mil deviation.
24*4882a593Smuzhiyun * UAC2 provides the value as a parameter as it impacts the endpoint required
25*4882a593Smuzhiyun * bandwidth.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun #define FBACK_FAST_MAX 5
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /* Feature Unit parameters */
30*4882a593Smuzhiyun struct uac_fu_params {
31*4882a593Smuzhiyun int id; /* Feature Unit ID */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun bool mute_present; /* mute control enable */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun bool volume_present; /* volume control enable */
36*4882a593Smuzhiyun s16 volume_min; /* min volume in 1/256 dB */
37*4882a593Smuzhiyun s16 volume_max; /* max volume in 1/256 dB */
38*4882a593Smuzhiyun s16 volume_res; /* volume resolution in 1/256 dB */
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun struct uac_params {
42*4882a593Smuzhiyun /* playback */
43*4882a593Smuzhiyun int p_chmask; /* channel mask */
44*4882a593Smuzhiyun int p_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
45*4882a593Smuzhiyun int p_ssize; /* sample size */
46*4882a593Smuzhiyun struct uac_fu_params p_fu; /* Feature Unit parameters */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* capture */
49*4882a593Smuzhiyun int c_chmask; /* channel mask */
50*4882a593Smuzhiyun int c_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
51*4882a593Smuzhiyun int c_ssize; /* sample size */
52*4882a593Smuzhiyun struct uac_fu_params c_fu; /* Feature Unit parameters */
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* rates are dynamic, in uac_rtd_params */
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun int ppm; /* difference between audio clk and usb clk */
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun int req_number; /* number of preallocated requests */
59*4882a593Smuzhiyun int fb_max; /* upper frequency drift feedback limit per-mil */
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun enum usb_state_index {
63*4882a593Smuzhiyun SET_INTERFACE_OUT,
64*4882a593Smuzhiyun SET_INTERFACE_IN,
65*4882a593Smuzhiyun SET_SAMPLE_RATE_OUT,
66*4882a593Smuzhiyun SET_SAMPLE_RATE_IN,
67*4882a593Smuzhiyun SET_VOLUME_OUT,
68*4882a593Smuzhiyun SET_VOLUME_IN,
69*4882a593Smuzhiyun SET_MUTE_OUT,
70*4882a593Smuzhiyun SET_MUTE_IN,
71*4882a593Smuzhiyun SET_AUDIO_CLK,
72*4882a593Smuzhiyun SET_USB_STATE_MAX,
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun enum stream_state_index {
76*4882a593Smuzhiyun STATE_OUT,
77*4882a593Smuzhiyun STATE_IN,
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun struct frame_number_data {
81*4882a593Smuzhiyun uint32_t fn_begin; /* frame number when starting statistics */
82*4882a593Smuzhiyun uint32_t fn_last; /* frame number in the latest statistics */
83*4882a593Smuzhiyun uint32_t fn_overflow; /* the time of frame number overflow */
84*4882a593Smuzhiyun uint32_t second; /* total seconds counted */
85*4882a593Smuzhiyun ktime_t time_begin; /* system time when starting statistics */
86*4882a593Smuzhiyun ktime_t time_last; /* system time in the latest statistics */
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun struct g_audio {
90*4882a593Smuzhiyun struct device *device;
91*4882a593Smuzhiyun bool usb_state[SET_USB_STATE_MAX];
92*4882a593Smuzhiyun bool stream_state[2];
93*4882a593Smuzhiyun struct work_struct work;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun struct frame_number_data *fn;
96*4882a593Smuzhiyun struct delayed_work ppm_work;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun struct usb_function func;
99*4882a593Smuzhiyun struct usb_gadget *gadget;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun struct usb_ep *in_ep;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun struct usb_ep *out_ep;
104*4882a593Smuzhiyun /* feedback IN endpoint corresponding to out_ep */
105*4882a593Smuzhiyun struct usb_ep *in_ep_fback;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Max packet size for all in_ep possible speeds */
108*4882a593Smuzhiyun unsigned int in_ep_maxpsize;
109*4882a593Smuzhiyun /* Max packet size for all out_ep possible speeds */
110*4882a593Smuzhiyun unsigned int out_ep_maxpsize;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* Notify UAC driver about control change */
113*4882a593Smuzhiyun int (*notify)(struct g_audio *g_audio, int unit_id, int cs);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* The ALSA Sound Card it represents on the USB-Client side */
116*4882a593Smuzhiyun struct snd_uac_chip *uac;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun struct uac_params params;
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun
func_to_g_audio(struct usb_function * f)121*4882a593Smuzhiyun static inline struct g_audio *func_to_g_audio(struct usb_function *f)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun return container_of(f, struct g_audio, func);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
num_channels(uint chanmask)126*4882a593Smuzhiyun static inline uint num_channels(uint chanmask)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun uint num = 0;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun while (chanmask) {
131*4882a593Smuzhiyun num += (chanmask & 1);
132*4882a593Smuzhiyun chanmask >>= 1;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun return num;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun * g_audio_setup - initialize one virtual ALSA sound card
140*4882a593Smuzhiyun * @g_audio: struct with filled params, in_ep_maxpsize, out_ep_maxpsize
141*4882a593Smuzhiyun * @pcm_name: the id string for a PCM instance of this sound card
142*4882a593Smuzhiyun * @card_name: name of this soundcard
143*4882a593Smuzhiyun *
144*4882a593Smuzhiyun * This sets up the single virtual ALSA sound card that may be exported by a
145*4882a593Smuzhiyun * gadget driver using this framework.
146*4882a593Smuzhiyun *
147*4882a593Smuzhiyun * Context: may sleep
148*4882a593Smuzhiyun *
149*4882a593Smuzhiyun * Returns zero on success, or a negative error on failure.
150*4882a593Smuzhiyun */
151*4882a593Smuzhiyun int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
152*4882a593Smuzhiyun const char *card_name);
153*4882a593Smuzhiyun void g_audio_cleanup(struct g_audio *g_audio);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun int u_audio_start_capture(struct g_audio *g_audio);
156*4882a593Smuzhiyun void u_audio_stop_capture(struct g_audio *g_audio);
157*4882a593Smuzhiyun int u_audio_start_playback(struct g_audio *g_audio);
158*4882a593Smuzhiyun void u_audio_stop_playback(struct g_audio *g_audio);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun int u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val);
161*4882a593Smuzhiyun int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate);
162*4882a593Smuzhiyun int u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val);
163*4882a593Smuzhiyun int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun int u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val);
166*4882a593Smuzhiyun int u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
167*4882a593Smuzhiyun int u_audio_get_mute(struct g_audio *g_audio, int playback, int *val);
168*4882a593Smuzhiyun int u_audio_set_mute(struct g_audio *g_audio, int playback, int val);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun void u_audio_suspend(struct g_audio *g_audio);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun #endif /* __U_AUDIO_H */
173