162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * u_audio.h -- interface to USB gadget "ALSA sound card" utilities
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2016
662306a36Sopenharmony_ci * Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __U_AUDIO_H
1062306a36Sopenharmony_ci#define __U_AUDIO_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/usb/composite.h>
1362306a36Sopenharmony_ci#include "uac_common.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Same maximum frequency deviation on the slower side as in
1762306a36Sopenharmony_ci * sound/usb/endpoint.c. Value is expressed in per-mil deviation.
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci#define FBACK_SLOW_MAX	250
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * Maximum frequency deviation on the faster side, default value for UAC1/2.
2362306a36Sopenharmony_ci * Value is expressed in per-mil deviation.
2462306a36Sopenharmony_ci * UAC2 provides the value as a parameter as it impacts the endpoint required
2562306a36Sopenharmony_ci * bandwidth.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ci#define FBACK_FAST_MAX 5
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* Feature Unit parameters */
3062306a36Sopenharmony_cistruct uac_fu_params {
3162306a36Sopenharmony_ci	int id;			/* Feature Unit ID */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	bool mute_present;	/* mute control enable */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	bool volume_present;	/* volume control enable */
3662306a36Sopenharmony_ci	s16 volume_min;		/* min volume in 1/256 dB */
3762306a36Sopenharmony_ci	s16 volume_max;		/* max volume in 1/256 dB */
3862306a36Sopenharmony_ci	s16 volume_res;		/* volume resolution in 1/256 dB */
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct uac_params {
4262306a36Sopenharmony_ci	/* playback */
4362306a36Sopenharmony_ci	int p_chmask;	/* channel mask */
4462306a36Sopenharmony_ci	int p_srates[UAC_MAX_RATES];	/* available rates in Hz (0 terminated list) */
4562306a36Sopenharmony_ci	int p_ssize;	/* sample size */
4662306a36Sopenharmony_ci	struct uac_fu_params p_fu;	/* Feature Unit parameters */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* capture */
4962306a36Sopenharmony_ci	int c_chmask;	/* channel mask */
5062306a36Sopenharmony_ci	int c_srates[UAC_MAX_RATES];	/* available rates in Hz (0 terminated list) */
5162306a36Sopenharmony_ci	int c_ssize;	/* sample size */
5262306a36Sopenharmony_ci	struct uac_fu_params c_fu;	/* Feature Unit parameters */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/* rates are dynamic, in uac_rtd_params */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	int req_number; /* number of preallocated requests */
5762306a36Sopenharmony_ci	int fb_max;	/* upper frequency drift feedback limit per-mil */
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct g_audio {
6162306a36Sopenharmony_ci	struct usb_function func;
6262306a36Sopenharmony_ci	struct usb_gadget *gadget;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	struct usb_ep *in_ep;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	struct usb_ep *out_ep;
6762306a36Sopenharmony_ci	/* feedback IN endpoint corresponding to out_ep */
6862306a36Sopenharmony_ci	struct usb_ep *in_ep_fback;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* Max packet size for all in_ep possible speeds */
7162306a36Sopenharmony_ci	unsigned int in_ep_maxpsize;
7262306a36Sopenharmony_ci	/* Max packet size for all out_ep possible speeds */
7362306a36Sopenharmony_ci	unsigned int out_ep_maxpsize;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* Notify UAC driver about control change */
7662306a36Sopenharmony_ci	int (*notify)(struct g_audio *g_audio, int unit_id, int cs);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	/* The ALSA Sound Card it represents on the USB-Client side */
7962306a36Sopenharmony_ci	struct snd_uac_chip *uac;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	struct uac_params params;
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic inline struct g_audio *func_to_g_audio(struct usb_function *f)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return container_of(f, struct g_audio, func);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic inline uint num_channels(uint chanmask)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	uint num = 0;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	while (chanmask) {
9462306a36Sopenharmony_ci		num += (chanmask & 1);
9562306a36Sopenharmony_ci		chanmask >>= 1;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return num;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * g_audio_setup - initialize one virtual ALSA sound card
10362306a36Sopenharmony_ci * @g_audio: struct with filled params, in_ep_maxpsize, out_ep_maxpsize
10462306a36Sopenharmony_ci * @pcm_name: the id string for a PCM instance of this sound card
10562306a36Sopenharmony_ci * @card_name: name of this soundcard
10662306a36Sopenharmony_ci *
10762306a36Sopenharmony_ci * This sets up the single virtual ALSA sound card that may be exported by a
10862306a36Sopenharmony_ci * gadget driver using this framework.
10962306a36Sopenharmony_ci *
11062306a36Sopenharmony_ci * Context: may sleep
11162306a36Sopenharmony_ci *
11262306a36Sopenharmony_ci * Returns zero on success, or a negative error on failure.
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_ciint g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
11562306a36Sopenharmony_ci					const char *card_name);
11662306a36Sopenharmony_civoid g_audio_cleanup(struct g_audio *g_audio);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciint u_audio_start_capture(struct g_audio *g_audio);
11962306a36Sopenharmony_civoid u_audio_stop_capture(struct g_audio *g_audio);
12062306a36Sopenharmony_ciint u_audio_start_playback(struct g_audio *g_audio);
12162306a36Sopenharmony_civoid u_audio_stop_playback(struct g_audio *g_audio);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciint u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val);
12462306a36Sopenharmony_ciint u_audio_set_capture_srate(struct g_audio *audio_dev, int srate);
12562306a36Sopenharmony_ciint u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val);
12662306a36Sopenharmony_ciint u_audio_set_playback_srate(struct g_audio *audio_dev, int srate);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciint u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val);
12962306a36Sopenharmony_ciint u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
13062306a36Sopenharmony_ciint u_audio_get_mute(struct g_audio *g_audio, int playback, int *val);
13162306a36Sopenharmony_ciint u_audio_set_mute(struct g_audio *g_audio, int playback, int val);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_civoid u_audio_suspend(struct g_audio *g_audio);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci#endif /* __U_AUDIO_H */
136