brintos

brintos / linux-shallow public Read only

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