/*
* f_uac2.c -- USB Audio Class 2.0 Function
*
* Copyright (C) 2011
* Yadwinder Singh (yadi.brar01@gmail.com)
* Jaswinder Singh (jaswinder.singh@linaro.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
/* Playback(USB-IN) Default Stereo - Fl/Fr */
static int p_chmask = 0x3;
module_param(p_chmask, uint, S_IRUGO);
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
/* Playback Default 48 KHz */
static int p_srate = 48000;
module_param(p_srate, uint, S_IRUGO);
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
/* Playback Default 16bits/sample */
static int p_ssize = 2;
module_param(p_ssize, uint, S_IRUGO);
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
static int c_chmask = 0x3;
module_param(c_chmask, uint, S_IRUGO);
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
/* Capture Default 64 KHz */
static int c_srate = 64000;
module_param(c_srate, uint, S_IRUGO);
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
/* Capture Default 16bits/sample */
static int c_ssize = 2;
module_param(c_ssize, uint, S_IRUGO);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0)
#define ALT_GET(x) ((x) & 0xff)
#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
#define INTF_GET(x) ((x >> 8) & 0xff)
/* Keep everyone on toes */
#define USB_XFERS 2
/*
* The driver implements a simple UAC_2 topology.
* USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
* ALSA_Playback -> IT_2 -> OT_4 -> USB-IN
* Capture and Playback sampling rates are independently
* controlled by two clock sources :
* CLK_5 := c_srate, and CLK_6 := p_srate
*/
#define USB_OUT_IT_ID 1
#define IO_IN_IT_ID 2
#define IO_OUT_OT_ID 3
#define USB_IN_OT_ID 4
#define USB_OUT_CLK_ID 5
#define USB_IN_CLK_ID 6
#define CONTROL_ABSENT 0
#define CONTROL_RDONLY 1
#define CONTROL_RDWR 3
#define CLK_FREQ_CTRL 0
#define CLK_VLD_CTRL 2
#define COPY_CTRL 0
#define CONN_CTRL 2
#define OVRLD_CTRL 4
#define CLSTR_CTRL 6
#define UNFLW_CTRL 8
#define OVFLW_CTRL 10
const char *uac2_name = "snd_uac2";
struct uac2_req {
struct uac2_rtd_params *pp; /* parent param */
struct usb_request *req;
};
struct uac2_rtd_params {
bool ep_enabled; /* if the ep is enabled */
/* Size of the ring buffer */
size_t dma_bytes;
unsigned char *dma_area;
struct snd_pcm_substream *ss;
/* Ring buffer */
ssize_t hw_ptr;
void *rbuf;
size_t period_size;
unsigned max_psize;
struct uac2_req ureq[USB_XFERS];
spinlock_t lock;
};
struct snd_uac2_chip {
struct platform_device pdev;
struct platform_driver pdrv;
struct uac2_rtd_params p_prm;
struct uac2_rtd_params c_prm;
struct snd_card *card;
struct snd_pcm *pcm;
};
#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
#define PRD_SIZE_MAX PAGE_SIZE
#define MIN_PERIODS 4
static struct snd_pcm_hardware uac2_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
| SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
.buffer_bytes_max = BUFF_SIZE_MAX,
.period_bytes_max = PRD_SIZE_MAX,
.periods_min = MIN_PERIODS,
};
struct audio_dev {
/* Currently active {Interface[15:8] | AltSettings[7:0]} */
__u16 ac_alt, as_out_alt,
|