// SPDX-License-Identifier: GPL-2.0-or-later
/*
*/
#include <linux/gfp.h>
#include <linux/init.h>
#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "usbaudio.h"
#include "helper.h"
#include "card.h"
#include "endpoint.h"
#include "pcm.h"
#include "clock.h"
#include "quirks.h"
#define EP_FLAG_RUNNING 1
#define EP_FLAG_STOPPING 2
/*
* snd_usb_endpoint is a model that abstracts everything related to an
* USB endpoint and its streaming.
*
* There are functions to activate and deactivate the streaming URBs and
* optional callbacks to let the pcm logic handle the actual content of the
* packets for playback and record. Thus, the bus streaming and the audio
* handlers are fully decoupled.
*
* There are two different types of endpoints in audio applications.
*
* SND_USB_ENDPOINT_TYPE_DATA handles full audio data payload for both
* inbound and outbound traffic.
*
* SND_USB_ENDPOINT_TYPE_SYNC endpoints are for inbound traffic only and
* expect the payload to carry Q10.14 / Q16.16 formatted sync information
* (3 or 4 bytes).
*
* Each endpoint has to be configured prior to being used by calling
* snd_usb_endpoint_set_params().
*
* The model incorporates a reference counting, so that multiple users
* can call snd_usb_endpoint_start() and snd_usb_endpoint_stop(), and
* only the first user will effectively start the URBs, and only the last
* one to stop it will tear the URBs down again.
*/
/*
* convert a sampling rate into our full speed format (fs/1000 in Q16.16)
* this will overflow at approx 524 kHz
*/
static inline unsigned get_usb_full_speed_rate(unsigned int rate)
{
return ((rate << 13) + 62) / 125;
}
/*
* convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
* this will overflow at approx 4 MHz
*/
static inline unsigned get_usb_high_speed_rate(unsigned int rate)
{
return ((rate << 10) + 62) / 125;
}
/*
* release a urb data
*/
static void release_urb_ctx(struct snd_urb_ctx *u)
{
if (u->buffer_size)
usb_free_coherent(u->ep->chip->dev, u->buffer_size,
u->urb->transfer_buffer,
u->urb->transfer_dma);
usb_free_urb(u->urb);
u->urb = NULL;
}
static const char *usb_error_string(int err)
{
switch (err) {
case -ENODEV:
return "no device";
case -ENOENT:
return "endpoint not enabled";
case -EPIPE:
return "endpoint stalled";
case -ENOSPC:
return "not enough bandwidth";
case -ESHUTDOWN:
return "device disabled";
case -EHOSTUNREACH:
return "device suspended";
case -EINVAL:
case -EAGAIN:
case -EFBIG:
case -EMSGSIZE:
return "internal error";
default:
return "unknown error";
}
}
/**
* snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
*
* @ep: The snd_usb_endpoint
*
* Determine whether an endpoint is driven by an implicit feedback
* data endpoint source.
*/
int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
{
return ep->implicit_fb_sync && usb_pipeout(ep->pipe);
}
/*
* Return the number of samples to be sent in the next packet
* for streaming based on information derived from sync endpoints
*
* This won't be used for implicit feedback which takes the packet size
* returned from the sync source
*/
static int slave_next_packet_size(struct snd_usb_endpoint *ep)
{
unsigned long flags;
int ret;
if (ep->fill_max)
return ep->maxframesize;
spin_lock_irqsave(&ep->lock, flags);
ep->phase = (ep->phase & 0xffff)
+ (ep->freqm << ep->datainterval);
ret = min(ep->phase >> 16, ep->maxframesize);
spin_unlock_irqrestore(&ep->lock, flags);
return ret;
}
/*
* Return the number of samples to be sent in the next packet
* for adaptive and synchronous endpoints
*/
static int next_packet_size(struct snd_usb_endpoint *ep)
{
int ret;
if (ep->fill_max)
return ep->maxframesize;
ep->sample_accum += ep->sample_rem;
if (ep->sample_accum >= ep->pps) {
ep->sample_accum -= ep->pps;
ret = ep->packsize[1];
} else {
ret = ep->packsize[0];
}
return ret;
}
/*
* snd_usb_endpoint_next_packet_size: Return the number of samples to be sent
* in the next packet
*/
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *ctx, int idx)
{
if (ctx->packet_size[idx])
return ctx->packet_size[idx];
else if (ep->sync_source)
return slave_next_packet_size(ep);
else
return next_packet_size(ep);
}
static void call_retire_callback(struct snd_usb_endpoint *ep,
struct urb *urb)
{
struct snd_usb_substream *data_subs;
data_subs = READ_ONCE(ep->data_subs);
if (data_subs && ep->retire_data_urb)
ep->retire_data_urb(data_subs, urb);
}
static void retire_outbound_urb(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *urb_ctx)
{
call_retire_callback(ep, urb_ctx->urb);
}
static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
struct snd_usb_endpoint *sender,
const struct urb *urb);
static void retire_inbound_urb(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *urb_ctx)
{
struct urb *urb = urb_ctx->urb;
struct snd_usb_endpoint *sync_sink;
if (unlikely(ep->skip_packets > 0)) {
ep->skip_packets--;
return;
}
sync_sink = READ_ONCE(ep->sync_sink);
if (sync_sink)
snd_usb_handle_sync_urb(sync_sink, ep, urb);
call_retire_callback(ep, urb);
}
static void prepare_silent_urb(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *ctx)
{
struct urb *urb = ctx->urb;
unsigned int offs = 0;
unsigned int extra = 0;
__le32 packet_length;
int i;
/* For tx_length_quirk, put packet length at start of packet */
if (ep->chip->tx_length_quirk)
extra = sizeof(packet_length);
for (i = 0; i < ctx->packets; ++i) {
unsigned int offset;
unsigned int length;
int counts;
counts = snd_usb_endpoint_next_packet_size(ep, ctx, i);
length = counts * ep->stride; /* number of silent bytes */
offset = offs * ep->stride + extra * i;
urb->iso_frame_desc[i].offset = offset;
urb->iso_frame_desc[i].length = length + extra;
if (extra) {
packet_length = cpu_to_le32(length);
memcpy(urb->transfer_buffer + offset,
&packet_le
|