cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usbusx2yaudio.c (27701B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   US-X2Y AUDIO
      4 *   Copyright (c) 2002-2004 by Karsten Wiese
      5 *
      6 *   based on
      7 *
      8 *   (Tentative) USB Audio Driver for ALSA
      9 *
     10 *   Main and PCM part
     11 *
     12 *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
     13 *
     14 *   Many codes borrowed from audio.c by
     15 *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
     16 *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
     17 */
     18
     19
     20#include <linux/interrupt.h>
     21#include <linux/slab.h>
     22#include <linux/usb.h>
     23#include <linux/moduleparam.h>
     24#include <sound/core.h>
     25#include <sound/info.h>
     26#include <sound/pcm.h>
     27#include <sound/pcm_params.h>
     28#include "usx2y.h"
     29#include "usbusx2y.h"
     30
     31/* Default value used for nr of packs per urb.
     32 * 1 to 4 have been tested ok on uhci.
     33 * To use 3 on ohci, you'd need a patch:
     34 * look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on
     35 * "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425"
     36 *
     37 * 1, 2 and 4 work out of the box on ohci, if I recall correctly.
     38 * Bigger is safer operation, smaller gives lower latencies.
     39 */
     40#define USX2Y_NRPACKS 4
     41
     42/* If your system works ok with this module's parameter
     43 * nrpacks set to 1, you might as well comment
     44 * this define out, and thereby produce smaller, faster code.
     45 * You'd also set USX2Y_NRPACKS to 1 then.
     46 */
     47#define USX2Y_NRPACKS_VARIABLE 1
     48
     49#ifdef USX2Y_NRPACKS_VARIABLE
     50static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */
     51#define  nr_of_packs() nrpacks
     52module_param(nrpacks, int, 0444);
     53MODULE_PARM_DESC(nrpacks, "Number of packets per URB.");
     54#else
     55#define nr_of_packs() USX2Y_NRPACKS
     56#endif
     57
     58static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs)
     59{
     60	struct urb	*urb = subs->completed_urb;
     61	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
     62	unsigned char	*cp;
     63	int		i, len, lens = 0, hwptr_done = subs->hwptr_done;
     64	int		cnt, blen;
     65	struct usx2ydev	*usx2y = subs->usx2y;
     66
     67	for (i = 0; i < nr_of_packs(); i++) {
     68		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
     69		if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
     70			snd_printk(KERN_ERR
     71				   "active frame status %i. Most probably some hardware problem.\n",
     72				   urb->iso_frame_desc[i].status);
     73			return urb->iso_frame_desc[i].status;
     74		}
     75		len = urb->iso_frame_desc[i].actual_length / usx2y->stride;
     76		if (!len) {
     77			snd_printd("0 == len ERROR!\n");
     78			continue;
     79		}
     80
     81		/* copy a data chunk */
     82		if ((hwptr_done + len) > runtime->buffer_size) {
     83			cnt = runtime->buffer_size - hwptr_done;
     84			blen = cnt * usx2y->stride;
     85			memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, blen);
     86			memcpy(runtime->dma_area, cp + blen, len * usx2y->stride - blen);
     87		} else {
     88			memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp,
     89			       len * usx2y->stride);
     90		}
     91		lens += len;
     92		hwptr_done += len;
     93		if (hwptr_done >= runtime->buffer_size)
     94			hwptr_done -= runtime->buffer_size;
     95	}
     96
     97	subs->hwptr_done = hwptr_done;
     98	subs->transfer_done += lens;
     99	/* update the pointer, call callback if necessary */
    100	if (subs->transfer_done >= runtime->period_size) {
    101		subs->transfer_done -= runtime->period_size;
    102		snd_pcm_period_elapsed(subs->pcm_substream);
    103	}
    104	return 0;
    105}
    106
    107/*
    108 * prepare urb for playback data pipe
    109 *
    110 * we copy the data directly from the pcm buffer.
    111 * the current position to be copied is held in hwptr field.
    112 * since a urb can handle only a single linear buffer, if the total
    113 * transferred area overflows the buffer boundary, we cannot send
    114 * it directly from the buffer.  thus the data is once copied to
    115 * a temporary buffer and urb points to that.
    116 */
    117static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs,
    118				  struct urb *cap_urb,
    119				  struct urb *urb)
    120{
    121	struct usx2ydev *usx2y = subs->usx2y;
    122	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
    123	int count, counts, pack, len;
    124
    125	count = 0;
    126	for (pack = 0; pack <  nr_of_packs(); pack++) {
    127		/* calculate the size of a packet */
    128		counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride;
    129		count += counts;
    130		if (counts < 43 || counts > 50) {
    131			snd_printk(KERN_ERR "should not be here with counts=%i\n", counts);
    132			return -EPIPE;
    133		}
    134		/* set up descriptor */
    135		urb->iso_frame_desc[pack].offset = pack ?
    136			urb->iso_frame_desc[pack - 1].offset +
    137			urb->iso_frame_desc[pack - 1].length :
    138			0;
    139		urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length;
    140	}
    141	if (atomic_read(&subs->state) >= STATE_PRERUNNING) {
    142		if (subs->hwptr + count > runtime->buffer_size) {
    143			/* err, the transferred area goes over buffer boundary.
    144			 * copy the data to the temp buffer.
    145			 */
    146			len = runtime->buffer_size - subs->hwptr;
    147			urb->transfer_buffer = subs->tmpbuf;
    148			memcpy(subs->tmpbuf, runtime->dma_area +
    149			       subs->hwptr * usx2y->stride, len * usx2y->stride);
    150			memcpy(subs->tmpbuf + len * usx2y->stride,
    151			       runtime->dma_area, (count - len) * usx2y->stride);
    152			subs->hwptr += count;
    153			subs->hwptr -= runtime->buffer_size;
    154		} else {
    155			/* set the buffer pointer */
    156			urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride;
    157			subs->hwptr += count;
    158			if (subs->hwptr >= runtime->buffer_size)
    159				subs->hwptr -= runtime->buffer_size;
    160		}
    161	} else {
    162		urb->transfer_buffer = subs->tmpbuf;
    163	}
    164	urb->transfer_buffer_length = count * usx2y->stride;
    165	return 0;
    166}
    167
    168/*
    169 * process after playback data complete
    170 *
    171 * update the current position and call callback if a period is processed.
    172 */
    173static void usx2y_urb_play_retire(struct snd_usx2y_substream *subs, struct urb *urb)
    174{
    175	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
    176	int		len = urb->actual_length / subs->usx2y->stride;
    177
    178	subs->transfer_done += len;
    179	subs->hwptr_done +=  len;
    180	if (subs->hwptr_done >= runtime->buffer_size)
    181		subs->hwptr_done -= runtime->buffer_size;
    182	if (subs->transfer_done >= runtime->period_size) {
    183		subs->transfer_done -= runtime->period_size;
    184		snd_pcm_period_elapsed(subs->pcm_substream);
    185	}
    186}
    187
    188static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, int frame)
    189{
    190	int err;
    191
    192	if (!urb)
    193		return -ENODEV;
    194	urb->start_frame = frame + NRURBS * nr_of_packs();  // let hcd do rollover sanity checks
    195	urb->hcpriv = NULL;
    196	urb->dev = subs->usx2y->dev; /* we need to set this at each time */
    197	err = usb_submit_urb(urb, GFP_ATOMIC);
    198	if (err < 0) {
    199		snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err);
    200		return err;
    201	}
    202	return 0;
    203}
    204
    205static int usx2y_usbframe_complete(struct snd_usx2y_substream *capsubs,
    206				   struct snd_usx2y_substream *playbacksubs,
    207				   int frame)
    208{
    209	int err, state;
    210	struct urb *urb = playbacksubs->completed_urb;
    211
    212	state = atomic_read(&playbacksubs->state);
    213	if (urb) {
    214		if (state == STATE_RUNNING)
    215			usx2y_urb_play_retire(playbacksubs, urb);
    216		else if (state >= STATE_PRERUNNING)
    217			atomic_inc(&playbacksubs->state);
    218	} else {
    219		switch (state) {
    220		case STATE_STARTING1:
    221			urb = playbacksubs->urb[0];
    222			atomic_inc(&playbacksubs->state);
    223			break;
    224		case STATE_STARTING2:
    225			urb = playbacksubs->urb[1];
    226			atomic_inc(&playbacksubs->state);
    227			break;
    228		}
    229	}
    230	if (urb) {
    231		err = usx2y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb);
    232		if (err)
    233			return err;
    234		err = usx2y_urb_submit(playbacksubs, urb, frame);
    235		if (err)
    236			return err;
    237	}
    238
    239	playbacksubs->completed_urb = NULL;
    240
    241	state = atomic_read(&capsubs->state);
    242	if (state >= STATE_PREPARED) {
    243		if (state == STATE_RUNNING) {
    244			err = usx2y_urb_capt_retire(capsubs);
    245			if (err)
    246				return err;
    247		} else if (state >= STATE_PRERUNNING) {
    248			atomic_inc(&capsubs->state);
    249		}
    250		err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame);
    251		if (err)
    252			return err;
    253	}
    254	capsubs->completed_urb = NULL;
    255	return 0;
    256}
    257
    258static void usx2y_clients_stop(struct usx2ydev *usx2y)
    259{
    260	struct snd_usx2y_substream *subs;
    261	struct urb *urb;
    262	int s, u;
    263
    264	for (s = 0; s < 4; s++) {
    265		subs = usx2y->subs[s];
    266		if (subs) {
    267			snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state));
    268			atomic_set(&subs->state, STATE_STOPPED);
    269		}
    270	}
    271	for (s = 0; s < 4; s++) {
    272		subs = usx2y->subs[s];
    273		if (subs) {
    274			if (atomic_read(&subs->state) >= STATE_PRERUNNING)
    275				snd_pcm_stop_xrun(subs->pcm_substream);
    276			for (u = 0; u < NRURBS; u++) {
    277				urb = subs->urb[u];
    278				if (urb)
    279					snd_printdd("%i status=%i start_frame=%i\n",
    280						    u, urb->status, urb->start_frame);
    281			}
    282		}
    283	}
    284	usx2y->prepare_subs = NULL;
    285	wake_up(&usx2y->prepare_wait_queue);
    286}
    287
    288static void usx2y_error_urb_status(struct usx2ydev *usx2y,
    289				   struct snd_usx2y_substream *subs, struct urb *urb)
    290{
    291	snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status);
    292	urb->status = 0;
    293	usx2y_clients_stop(usx2y);
    294}
    295
    296static void i_usx2y_urb_complete(struct urb *urb)
    297{
    298	struct snd_usx2y_substream *subs = urb->context;
    299	struct usx2ydev *usx2y = subs->usx2y;
    300	struct snd_usx2y_substream *capsubs, *playbacksubs;
    301
    302	if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) {
    303		snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
    304			    usb_get_current_frame_number(usx2y->dev),
    305			    subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
    306			    urb->status, urb->start_frame);
    307		return;
    308	}
    309	if (unlikely(urb->status)) {
    310		usx2y_error_urb_status(usx2y, subs, urb);
    311		return;
    312	}
    313
    314	subs->completed_urb = urb;
    315
    316	capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
    317	playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
    318
    319	if (capsubs->completed_urb &&
    320	    atomic_read(&capsubs->state) >= STATE_PREPARED &&
    321	    (playbacksubs->completed_urb ||
    322	     atomic_read(&playbacksubs->state) < STATE_PREPARED)) {
    323		if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) {
    324			usx2y->wait_iso_frame += nr_of_packs();
    325		} else {
    326			snd_printdd("\n");
    327			usx2y_clients_stop(usx2y);
    328		}
    329	}
    330}
    331
    332static void usx2y_urbs_set_complete(struct usx2ydev *usx2y,
    333				    void (*complete)(struct urb *))
    334{
    335	struct snd_usx2y_substream *subs;
    336	struct urb *urb;
    337	int s, u;
    338
    339	for (s = 0; s < 4; s++) {
    340		subs = usx2y->subs[s];
    341		if (subs) {
    342			for (u = 0; u < NRURBS; u++) {
    343				urb = subs->urb[u];
    344				if (urb)
    345					urb->complete = complete;
    346			}
    347		}
    348	}
    349}
    350
    351static void usx2y_subs_startup_finish(struct usx2ydev *usx2y)
    352{
    353	usx2y_urbs_set_complete(usx2y, i_usx2y_urb_complete);
    354	usx2y->prepare_subs = NULL;
    355}
    356
    357static void i_usx2y_subs_startup(struct urb *urb)
    358{
    359	struct snd_usx2y_substream *subs = urb->context;
    360	struct usx2ydev *usx2y = subs->usx2y;
    361	struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs;
    362
    363	if (prepare_subs) {
    364		if (urb->start_frame == prepare_subs->urb[0]->start_frame) {
    365			usx2y_subs_startup_finish(usx2y);
    366			atomic_inc(&prepare_subs->state);
    367			wake_up(&usx2y->prepare_wait_queue);
    368		}
    369	}
    370
    371	i_usx2y_urb_complete(urb);
    372}
    373
    374static void usx2y_subs_prepare(struct snd_usx2y_substream *subs)
    375{
    376	snd_printdd("usx2y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n",
    377		    subs, subs->endpoint, subs->urb[0], subs->urb[1]);
    378	/* reset the pointer */
    379	subs->hwptr = 0;
    380	subs->hwptr_done = 0;
    381	subs->transfer_done = 0;
    382}
    383
    384static void usx2y_urb_release(struct urb **urb, int free_tb)
    385{
    386	if (*urb) {
    387		usb_kill_urb(*urb);
    388		if (free_tb)
    389			kfree((*urb)->transfer_buffer);
    390		usb_free_urb(*urb);
    391		*urb = NULL;
    392	}
    393}
    394
    395/*
    396 * release a substreams urbs
    397 */
    398static void usx2y_urbs_release(struct snd_usx2y_substream *subs)
    399{
    400	int i;
    401
    402	snd_printdd("%s %i\n", __func__, subs->endpoint);
    403	for (i = 0; i < NRURBS; i++)
    404		usx2y_urb_release(subs->urb + i,
    405				  subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
    406
    407	kfree(subs->tmpbuf);
    408	subs->tmpbuf = NULL;
    409}
    410
    411/*
    412 * initialize a substream's urbs
    413 */
    414static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs)
    415{
    416	int i;
    417	unsigned int pipe;
    418	int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
    419	struct usb_device *dev = subs->usx2y->dev;
    420	struct urb **purb;
    421
    422	pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
    423			usb_rcvisocpipe(dev, subs->endpoint);
    424	subs->maxpacksize = usb_maxpacket(dev, pipe);
    425	if (!subs->maxpacksize)
    426		return -EINVAL;
    427
    428	if (is_playback && !subs->tmpbuf) {	/* allocate a temporary buffer for playback */
    429		subs->tmpbuf = kcalloc(nr_of_packs(), subs->maxpacksize, GFP_KERNEL);
    430		if (!subs->tmpbuf)
    431			return -ENOMEM;
    432	}
    433	/* allocate and initialize data urbs */
    434	for (i = 0; i < NRURBS; i++) {
    435		purb = subs->urb + i;
    436		if (*purb) {
    437			usb_kill_urb(*purb);
    438			continue;
    439		}
    440		*purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL);
    441		if (!*purb) {
    442			usx2y_urbs_release(subs);
    443			return -ENOMEM;
    444		}
    445		if (!is_playback && !(*purb)->transfer_buffer) {
    446			/* allocate a capture buffer per urb */
    447			(*purb)->transfer_buffer =
    448				kmalloc_array(subs->maxpacksize,
    449					      nr_of_packs(), GFP_KERNEL);
    450			if (!(*purb)->transfer_buffer) {
    451				usx2y_urbs_release(subs);
    452				return -ENOMEM;
    453			}
    454		}
    455		(*purb)->dev = dev;
    456		(*purb)->pipe = pipe;
    457		(*purb)->number_of_packets = nr_of_packs();
    458		(*purb)->context = subs;
    459		(*purb)->interval = 1;
    460		(*purb)->complete = i_usx2y_subs_startup;
    461	}
    462	return 0;
    463}
    464
    465static void usx2y_subs_startup(struct snd_usx2y_substream *subs)
    466{
    467	struct usx2ydev *usx2y = subs->usx2y;
    468
    469	usx2y->prepare_subs = subs;
    470	subs->urb[0]->start_frame = -1;
    471	wmb();
    472	usx2y_urbs_set_complete(usx2y, i_usx2y_subs_startup);
    473}
    474
    475static int usx2y_urbs_start(struct snd_usx2y_substream *subs)
    476{
    477	int i, err;
    478	struct usx2ydev *usx2y = subs->usx2y;
    479	struct urb *urb;
    480	unsigned long pack;
    481
    482	err = usx2y_urbs_allocate(subs);
    483	if (err < 0)
    484		return err;
    485	subs->completed_urb = NULL;
    486	for (i = 0; i < 4; i++) {
    487		struct snd_usx2y_substream *subs = usx2y->subs[i];
    488
    489		if (subs && atomic_read(&subs->state) >= STATE_PREPARED)
    490			goto start;
    491	}
    492
    493 start:
    494	usx2y_subs_startup(subs);
    495	for (i = 0; i < NRURBS; i++) {
    496		urb = subs->urb[i];
    497		if (usb_pipein(urb->pipe)) {
    498			if (!i)
    499				atomic_set(&subs->state, STATE_STARTING3);
    500			urb->dev = usx2y->dev;
    501			for (pack = 0; pack < nr_of_packs(); pack++) {
    502				urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
    503				urb->iso_frame_desc[pack].length = subs->maxpacksize;
    504			}
    505			urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs();
    506			err = usb_submit_urb(urb, GFP_ATOMIC);
    507			if (err < 0) {
    508				snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
    509				err = -EPIPE;
    510				goto cleanup;
    511			} else {
    512				if (!i)
    513					usx2y->wait_iso_frame = urb->start_frame;
    514			}
    515			urb->transfer_flags = 0;
    516		} else {
    517			atomic_set(&subs->state, STATE_STARTING1);
    518			break;
    519		}
    520	}
    521	err = 0;
    522	wait_event(usx2y->prepare_wait_queue, !usx2y->prepare_subs);
    523	if (atomic_read(&subs->state) != STATE_PREPARED)
    524		err = -EPIPE;
    525
    526 cleanup:
    527	if (err) {
    528		usx2y_subs_startup_finish(usx2y);
    529		usx2y_clients_stop(usx2y);	// something is completely wrong > stop everything
    530	}
    531	return err;
    532}
    533
    534/*
    535 * return the current pcm pointer.  just return the hwptr_done value.
    536 */
    537static snd_pcm_uframes_t snd_usx2y_pcm_pointer(struct snd_pcm_substream *substream)
    538{
    539	struct snd_usx2y_substream *subs = substream->runtime->private_data;
    540
    541	return subs->hwptr_done;
    542}
    543
    544/*
    545 * start/stop substream
    546 */
    547static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
    548{
    549	struct snd_usx2y_substream *subs = substream->runtime->private_data;
    550
    551	switch (cmd) {
    552	case SNDRV_PCM_TRIGGER_START:
    553		snd_printdd("%s(START)\n", __func__);
    554		if (atomic_read(&subs->state) == STATE_PREPARED &&
    555		    atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) {
    556			atomic_set(&subs->state, STATE_PRERUNNING);
    557		} else {
    558			snd_printdd("\n");
    559			return -EPIPE;
    560		}
    561		break;
    562	case SNDRV_PCM_TRIGGER_STOP:
    563		snd_printdd("%s(STOP)\n", __func__);
    564		if (atomic_read(&subs->state) >= STATE_PRERUNNING)
    565			atomic_set(&subs->state, STATE_PREPARED);
    566		break;
    567	default:
    568		return -EINVAL;
    569	}
    570	return 0;
    571}
    572
    573/*
    574 * allocate a buffer, setup samplerate
    575 *
    576 * so far we use a physically linear buffer although packetize transfer
    577 * doesn't need a continuous area.
    578 * if sg buffer is supported on the later version of alsa, we'll follow
    579 * that.
    580 */
    581struct s_c2 {
    582	char c1, c2;
    583};
    584
    585static const struct s_c2 setrate_44100[] = {
    586	{ 0x14, 0x08},	// this line sets 44100, well actually a little less
    587	{ 0x18, 0x40},	// only tascam / frontier design knows the further lines .......
    588	{ 0x18, 0x42},
    589	{ 0x18, 0x45},
    590	{ 0x18, 0x46},
    591	{ 0x18, 0x48},
    592	{ 0x18, 0x4A},
    593	{ 0x18, 0x4C},
    594	{ 0x18, 0x4E},
    595	{ 0x18, 0x50},
    596	{ 0x18, 0x52},
    597	{ 0x18, 0x54},
    598	{ 0x18, 0x56},
    599	{ 0x18, 0x58},
    600	{ 0x18, 0x5A},
    601	{ 0x18, 0x5C},
    602	{ 0x18, 0x5E},
    603	{ 0x18, 0x60},
    604	{ 0x18, 0x62},
    605	{ 0x18, 0x64},
    606	{ 0x18, 0x66},
    607	{ 0x18, 0x68},
    608	{ 0x18, 0x6A},
    609	{ 0x18, 0x6C},
    610	{ 0x18, 0x6E},
    611	{ 0x18, 0x70},
    612	{ 0x18, 0x72},
    613	{ 0x18, 0x74},
    614	{ 0x18, 0x76},
    615	{ 0x18, 0x78},
    616	{ 0x18, 0x7A},
    617	{ 0x18, 0x7C},
    618	{ 0x18, 0x7E}
    619};
    620
    621static const struct s_c2 setrate_48000[] = {
    622	{ 0x14, 0x09},	// this line sets 48000, well actually a little less
    623	{ 0x18, 0x40},	// only tascam / frontier design knows the further lines .......
    624	{ 0x18, 0x42},
    625	{ 0x18, 0x45},
    626	{ 0x18, 0x46},
    627	{ 0x18, 0x48},
    628	{ 0x18, 0x4A},
    629	{ 0x18, 0x4C},
    630	{ 0x18, 0x4E},
    631	{ 0x18, 0x50},
    632	{ 0x18, 0x52},
    633	{ 0x18, 0x54},
    634	{ 0x18, 0x56},
    635	{ 0x18, 0x58},
    636	{ 0x18, 0x5A},
    637	{ 0x18, 0x5C},
    638	{ 0x18, 0x5E},
    639	{ 0x18, 0x60},
    640	{ 0x18, 0x62},
    641	{ 0x18, 0x64},
    642	{ 0x18, 0x66},
    643	{ 0x18, 0x68},
    644	{ 0x18, 0x6A},
    645	{ 0x18, 0x6C},
    646	{ 0x18, 0x6E},
    647	{ 0x18, 0x70},
    648	{ 0x18, 0x73},
    649	{ 0x18, 0x74},
    650	{ 0x18, 0x76},
    651	{ 0x18, 0x78},
    652	{ 0x18, 0x7A},
    653	{ 0x18, 0x7C},
    654	{ 0x18, 0x7E}
    655};
    656
    657#define NOOF_SETRATE_URBS ARRAY_SIZE(setrate_48000)
    658
    659static void i_usx2y_04int(struct urb *urb)
    660{
    661	struct usx2ydev *usx2y = urb->context;
    662
    663	if (urb->status)
    664		snd_printk(KERN_ERR "snd_usx2y_04int() urb->status=%i\n", urb->status);
    665	if (!--usx2y->us04->len)
    666		wake_up(&usx2y->in04_wait_queue);
    667}
    668
    669static int usx2y_rate_set(struct usx2ydev *usx2y, int rate)
    670{
    671	int err = 0, i;
    672	struct snd_usx2y_urb_seq *us = NULL;
    673	int *usbdata = NULL;
    674	const struct s_c2 *ra = rate == 48000 ? setrate_48000 : setrate_44100;
    675	struct urb *urb;
    676
    677	if (usx2y->rate != rate) {
    678		us = kzalloc(struct_size(us, urb, NOOF_SETRATE_URBS),
    679			     GFP_KERNEL);
    680		if (!us) {
    681			err = -ENOMEM;
    682			goto cleanup;
    683		}
    684		usbdata = kmalloc_array(NOOF_SETRATE_URBS, sizeof(int),
    685					GFP_KERNEL);
    686		if (!usbdata) {
    687			err = -ENOMEM;
    688			goto cleanup;
    689		}
    690		for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
    691			us->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
    692			if (!us->urb[i]) {
    693				err = -ENOMEM;
    694				goto cleanup;
    695			}
    696			((char *)(usbdata + i))[0] = ra[i].c1;
    697			((char *)(usbdata + i))[1] = ra[i].c2;
    698			usb_fill_bulk_urb(us->urb[i], usx2y->dev, usb_sndbulkpipe(usx2y->dev, 4),
    699					  usbdata + i, 2, i_usx2y_04int, usx2y);
    700		}
    701		err = usb_urb_ep_type_check(us->urb[0]);
    702		if (err < 0)
    703			goto cleanup;
    704		us->submitted =	0;
    705		us->len =	NOOF_SETRATE_URBS;
    706		usx2y->us04 =	us;
    707		wait_event_timeout(usx2y->in04_wait_queue, !us->len, HZ);
    708		usx2y->us04 =	NULL;
    709		if (us->len)
    710			err = -ENODEV;
    711	cleanup:
    712		if (us) {
    713			us->submitted =	2*NOOF_SETRATE_URBS;
    714			for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
    715				urb = us->urb[i];
    716				if (!urb)
    717					continue;
    718				if (urb->status) {
    719					if (!err)
    720						err = -ENODEV;
    721					usb_kill_urb(urb);
    722				}
    723				usb_free_urb(urb);
    724			}
    725			usx2y->us04 = NULL;
    726			kfree(usbdata);
    727			kfree(us);
    728			if (!err)
    729				usx2y->rate = rate;
    730		}
    731	}
    732
    733	return err;
    734}
    735
    736static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format)
    737{
    738	int alternate, err;
    739	struct list_head *p;
    740
    741	if (format == SNDRV_PCM_FORMAT_S24_3LE) {
    742		alternate = 2;
    743		usx2y->stride = 6;
    744	} else {
    745		alternate = 1;
    746		usx2y->stride = 4;
    747	}
    748	list_for_each(p, &usx2y->midi_list) {
    749		snd_usbmidi_input_stop(p);
    750	}
    751	usb_kill_urb(usx2y->in04_urb);
    752	err = usb_set_interface(usx2y->dev, 0, alternate);
    753	if (err) {
    754		snd_printk(KERN_ERR "usb_set_interface error\n");
    755		return err;
    756	}
    757	usx2y->in04_urb->dev = usx2y->dev;
    758	err = usb_submit_urb(usx2y->in04_urb, GFP_KERNEL);
    759	list_for_each(p, &usx2y->midi_list) {
    760		snd_usbmidi_input_start(p);
    761	}
    762	usx2y->format = format;
    763	usx2y->rate = 0;
    764	return err;
    765}
    766
    767
    768static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream,
    769				   struct snd_pcm_hw_params *hw_params)
    770{
    771	int			err = 0;
    772	unsigned int		rate = params_rate(hw_params);
    773	snd_pcm_format_t	format = params_format(hw_params);
    774	struct snd_card *card = substream->pstr->pcm->card;
    775	struct usx2ydev	*dev = usx2y(card);
    776	struct snd_usx2y_substream *subs;
    777	struct snd_pcm_substream *test_substream;
    778	int i;
    779
    780	mutex_lock(&usx2y(card)->pcm_mutex);
    781	snd_printdd("snd_usx2y_hw_params(%p, %p)\n", substream, hw_params);
    782	/* all pcm substreams off one usx2y have to operate at the same
    783	 * rate & format
    784	 */
    785	for (i = 0; i < dev->pcm_devs * 2; i++) {
    786		subs = dev->subs[i];
    787		if (!subs)
    788			continue;
    789		test_substream = subs->pcm_substream;
    790		if (!test_substream || test_substream == substream ||
    791		    !test_substream->runtime)
    792			continue;
    793		if ((test_substream->runtime->format &&
    794		     test_substream->runtime->format != format) ||
    795		    (test_substream->runtime->rate &&
    796		     test_substream->runtime->rate != rate)) {
    797			err = -EINVAL;
    798			goto error;
    799		}
    800	}
    801
    802 error:
    803	mutex_unlock(&usx2y(card)->pcm_mutex);
    804	return err;
    805}
    806
    807/*
    808 * free the buffer
    809 */
    810static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream)
    811{
    812	struct snd_pcm_runtime *runtime = substream->runtime;
    813	struct snd_usx2y_substream *subs = runtime->private_data;
    814	struct snd_usx2y_substream *cap_subs, *playback_subs;
    815
    816	mutex_lock(&subs->usx2y->pcm_mutex);
    817	snd_printdd("snd_usx2y_hw_free(%p)\n", substream);
    818
    819	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    820		cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
    821		atomic_set(&subs->state, STATE_STOPPED);
    822		usx2y_urbs_release(subs);
    823		if (!cap_subs->pcm_substream ||
    824		    !cap_subs->pcm_substream->runtime ||
    825		    !cap_subs->pcm_substream->runtime->status ||
    826		    cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
    827			atomic_set(&cap_subs->state, STATE_STOPPED);
    828			usx2y_urbs_release(cap_subs);
    829		}
    830	} else {
    831		playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK];
    832		if (atomic_read(&playback_subs->state) < STATE_PREPARED) {
    833			atomic_set(&subs->state, STATE_STOPPED);
    834			usx2y_urbs_release(subs);
    835		}
    836	}
    837	mutex_unlock(&subs->usx2y->pcm_mutex);
    838	return 0;
    839}
    840
    841/*
    842 * prepare callback
    843 *
    844 * set format and initialize urbs
    845 */
    846static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream)
    847{
    848	struct snd_pcm_runtime *runtime = substream->runtime;
    849	struct snd_usx2y_substream *subs = runtime->private_data;
    850	struct usx2ydev *usx2y = subs->usx2y;
    851	struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE];
    852	int err = 0;
    853
    854	snd_printdd("%s(%p)\n", __func__, substream);
    855
    856	mutex_lock(&usx2y->pcm_mutex);
    857	usx2y_subs_prepare(subs);
    858	// Start hardware streams
    859	// SyncStream first....
    860	if (atomic_read(&capsubs->state) < STATE_PREPARED) {
    861		if (usx2y->format != runtime->format) {
    862			err = usx2y_format_set(usx2y, runtime->format);
    863			if (err < 0)
    864				goto up_prepare_mutex;
    865		}
    866		if (usx2y->rate != runtime->rate) {
    867			err = usx2y_rate_set(usx2y, runtime->rate);
    868			if (err < 0)
    869				goto up_prepare_mutex;
    870		}
    871		snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe");
    872		err = usx2y_urbs_start(capsubs);
    873		if (err < 0)
    874			goto up_prepare_mutex;
    875	}
    876
    877	if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED)
    878		err = usx2y_urbs_start(subs);
    879
    880 up_prepare_mutex:
    881	mutex_unlock(&usx2y->pcm_mutex);
    882	return err;
    883}
    884
    885static const struct snd_pcm_hardware snd_usx2y_2c = {
    886	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    887				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
    888				 SNDRV_PCM_INFO_MMAP_VALID |
    889				 SNDRV_PCM_INFO_BATCH),
    890	.formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
    891	.rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
    892	.rate_min =                44100,
    893	.rate_max =                48000,
    894	.channels_min =            2,
    895	.channels_max =            2,
    896	.buffer_bytes_max =	(2*128*1024),
    897	.period_bytes_min =	64,
    898	.period_bytes_max =	(128*1024),
    899	.periods_min =		2,
    900	.periods_max =		1024,
    901	.fifo_size =              0
    902};
    903
    904static int snd_usx2y_pcm_open(struct snd_pcm_substream *substream)
    905{
    906	struct snd_usx2y_substream	*subs =
    907		((struct snd_usx2y_substream **)
    908		 snd_pcm_substream_chip(substream))[substream->stream];
    909	struct snd_pcm_runtime	*runtime = substream->runtime;
    910
    911	if (subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)
    912		return -EBUSY;
    913
    914	runtime->hw = snd_usx2y_2c;
    915	runtime->private_data = subs;
    916	subs->pcm_substream = substream;
    917	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
    918	return 0;
    919}
    920
    921static int snd_usx2y_pcm_close(struct snd_pcm_substream *substream)
    922{
    923	struct snd_pcm_runtime *runtime = substream->runtime;
    924	struct snd_usx2y_substream *subs = runtime->private_data;
    925
    926	subs->pcm_substream = NULL;
    927
    928	return 0;
    929}
    930
    931static const struct snd_pcm_ops snd_usx2y_pcm_ops = {
    932	.open =		snd_usx2y_pcm_open,
    933	.close =	snd_usx2y_pcm_close,
    934	.hw_params =	snd_usx2y_pcm_hw_params,
    935	.hw_free =	snd_usx2y_pcm_hw_free,
    936	.prepare =	snd_usx2y_pcm_prepare,
    937	.trigger =	snd_usx2y_pcm_trigger,
    938	.pointer =	snd_usx2y_pcm_pointer,
    939};
    940
    941/*
    942 * free a usb stream instance
    943 */
    944static void usx2y_audio_stream_free(struct snd_usx2y_substream **usx2y_substream)
    945{
    946	int stream;
    947
    948	for_each_pcm_streams(stream) {
    949		kfree(usx2y_substream[stream]);
    950		usx2y_substream[stream] = NULL;
    951	}
    952}
    953
    954static void snd_usx2y_pcm_private_free(struct snd_pcm *pcm)
    955{
    956	struct snd_usx2y_substream **usx2y_stream = pcm->private_data;
    957
    958	if (usx2y_stream)
    959		usx2y_audio_stream_free(usx2y_stream);
    960}
    961
    962static int usx2y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint)
    963{
    964	struct snd_pcm *pcm;
    965	int err, i;
    966	struct snd_usx2y_substream **usx2y_substream =
    967		usx2y(card)->subs + 2 * usx2y(card)->pcm_devs;
    968
    969	for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
    970	     i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
    971		usx2y_substream[i] = kzalloc(sizeof(struct snd_usx2y_substream), GFP_KERNEL);
    972		if (!usx2y_substream[i])
    973			return -ENOMEM;
    974
    975		usx2y_substream[i]->usx2y = usx2y(card);
    976	}
    977
    978	if (playback_endpoint)
    979		usx2y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
    980	usx2y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
    981
    982	err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usx2y(card)->pcm_devs,
    983			  playback_endpoint ? 1 : 0, 1,
    984			  &pcm);
    985	if (err < 0) {
    986		usx2y_audio_stream_free(usx2y_substream);
    987		return err;
    988	}
    989
    990	if (playback_endpoint)
    991		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_pcm_ops);
    992	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_pcm_ops);
    993
    994	pcm->private_data = usx2y_substream;
    995	pcm->private_free = snd_usx2y_pcm_private_free;
    996	pcm->info_flags = 0;
    997
    998	sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usx2y(card)->pcm_devs);
    999
   1000	if (playback_endpoint) {
   1001		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
   1002					   SNDRV_DMA_TYPE_CONTINUOUS,
   1003					   NULL,
   1004					   64*1024, 128*1024);
   1005	}
   1006
   1007	snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
   1008				   SNDRV_DMA_TYPE_CONTINUOUS,
   1009				   NULL,
   1010				   64*1024, 128*1024);
   1011	usx2y(card)->pcm_devs++;
   1012
   1013	return 0;
   1014}
   1015
   1016/*
   1017 * create a chip instance and set its names.
   1018 */
   1019int usx2y_audio_create(struct snd_card *card)
   1020{
   1021	int err;
   1022
   1023	err = usx2y_audio_stream_new(card, 0xA, 0x8);
   1024	if (err < 0)
   1025		return err;
   1026	if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) == USB_ID_US428) {
   1027		err = usx2y_audio_stream_new(card, 0, 0xA);
   1028		if (err < 0)
   1029			return err;
   1030	}
   1031	if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) != USB_ID_US122)
   1032		err = usx2y_rate_set(usx2y(card), 44100);	// Lets us428 recognize output-volume settings, disturbs us122.
   1033	return err;
   1034}