162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Empiatech em28x1 audio extension
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci// Copyright (C) 2007-2016 Mauro Carvalho Chehab
862306a36Sopenharmony_ci//	- Port to work with the in-kernel driver
962306a36Sopenharmony_ci//	- Cleanups, fixes, alsa-controls, etc.
1062306a36Sopenharmony_ci//
1162306a36Sopenharmony_ci// This driver is based on my previous au600 usb pstn audio driver
1262306a36Sopenharmony_ci// and inherits all the copyrights
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "em28xx.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/kernel.h>
1762306a36Sopenharmony_ci#include <linux/usb.h>
1862306a36Sopenharmony_ci#include <linux/init.h>
1962306a36Sopenharmony_ci#include <linux/sound.h>
2062306a36Sopenharmony_ci#include <linux/spinlock.h>
2162306a36Sopenharmony_ci#include <linux/soundcard.h>
2262306a36Sopenharmony_ci#include <linux/slab.h>
2362306a36Sopenharmony_ci#include <linux/module.h>
2462306a36Sopenharmony_ci#include <sound/core.h>
2562306a36Sopenharmony_ci#include <sound/pcm.h>
2662306a36Sopenharmony_ci#include <sound/pcm_params.h>
2762306a36Sopenharmony_ci#include <sound/info.h>
2862306a36Sopenharmony_ci#include <sound/initval.h>
2962306a36Sopenharmony_ci#include <sound/control.h>
3062306a36Sopenharmony_ci#include <sound/tlv.h>
3162306a36Sopenharmony_ci#include <sound/ac97_codec.h>
3262306a36Sopenharmony_ci#include <media/v4l2-common.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic int debug;
3562306a36Sopenharmony_cimodule_param(debug, int, 0644);
3662306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "activates debug info");
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define EM28XX_MAX_AUDIO_BUFS		5
3962306a36Sopenharmony_ci#define EM28XX_MIN_AUDIO_PACKETS	64
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define dprintk(fmt, arg...) do {					\
4262306a36Sopenharmony_ci	if (debug)						\
4362306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
4462306a36Sopenharmony_ci			   "video: %s: " fmt, __func__, ## arg);	\
4562306a36Sopenharmony_ci} while (0)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic int em28xx_deinit_isoc_audio(struct em28xx *dev)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	int i;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	dprintk("Stopping isoc\n");
5462306a36Sopenharmony_ci	for (i = 0; i < dev->adev.num_urb; i++) {
5562306a36Sopenharmony_ci		struct urb *urb = dev->adev.urb[i];
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci		if (!irqs_disabled())
5862306a36Sopenharmony_ci			usb_kill_urb(urb);
5962306a36Sopenharmony_ci		else
6062306a36Sopenharmony_ci			usb_unlink_urb(urb);
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return 0;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic void em28xx_audio_isocirq(struct urb *urb)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct em28xx            *dev = urb->context;
6962306a36Sopenharmony_ci	int                      i;
7062306a36Sopenharmony_ci	unsigned int             oldptr;
7162306a36Sopenharmony_ci	int                      period_elapsed = 0;
7262306a36Sopenharmony_ci	int                      status;
7362306a36Sopenharmony_ci	unsigned char            *cp;
7462306a36Sopenharmony_ci	unsigned int             stride;
7562306a36Sopenharmony_ci	struct snd_pcm_substream *substream;
7662306a36Sopenharmony_ci	struct snd_pcm_runtime   *runtime;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (dev->disconnected) {
7962306a36Sopenharmony_ci		dprintk("device disconnected while streaming. URB status=%d.\n",
8062306a36Sopenharmony_ci			urb->status);
8162306a36Sopenharmony_ci		atomic_set(&dev->adev.stream_started, 0);
8262306a36Sopenharmony_ci		return;
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	switch (urb->status) {
8662306a36Sopenharmony_ci	case 0:             /* success */
8762306a36Sopenharmony_ci	case -ETIMEDOUT:    /* NAK */
8862306a36Sopenharmony_ci		break;
8962306a36Sopenharmony_ci	case -ECONNRESET:   /* kill */
9062306a36Sopenharmony_ci	case -ENOENT:
9162306a36Sopenharmony_ci	case -ESHUTDOWN:
9262306a36Sopenharmony_ci		return;
9362306a36Sopenharmony_ci	default:            /* error */
9462306a36Sopenharmony_ci		dprintk("urb completion error %d.\n", urb->status);
9562306a36Sopenharmony_ci		break;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (atomic_read(&dev->adev.stream_started) == 0)
9962306a36Sopenharmony_ci		return;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (dev->adev.capture_pcm_substream) {
10262306a36Sopenharmony_ci		substream = dev->adev.capture_pcm_substream;
10362306a36Sopenharmony_ci		runtime = substream->runtime;
10462306a36Sopenharmony_ci		stride = runtime->frame_bits >> 3;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci		for (i = 0; i < urb->number_of_packets; i++) {
10762306a36Sopenharmony_ci			unsigned long flags;
10862306a36Sopenharmony_ci			int length =
10962306a36Sopenharmony_ci			    urb->iso_frame_desc[i].actual_length / stride;
11062306a36Sopenharmony_ci			cp = (unsigned char *)urb->transfer_buffer +
11162306a36Sopenharmony_ci			    urb->iso_frame_desc[i].offset;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci			if (!length)
11462306a36Sopenharmony_ci				continue;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci			oldptr = dev->adev.hwptr_done_capture;
11762306a36Sopenharmony_ci			if (oldptr + length >= runtime->buffer_size) {
11862306a36Sopenharmony_ci				unsigned int cnt =
11962306a36Sopenharmony_ci				    runtime->buffer_size - oldptr;
12062306a36Sopenharmony_ci				memcpy(runtime->dma_area + oldptr * stride, cp,
12162306a36Sopenharmony_ci				       cnt * stride);
12262306a36Sopenharmony_ci				memcpy(runtime->dma_area, cp + cnt * stride,
12362306a36Sopenharmony_ci				       length * stride - cnt * stride);
12462306a36Sopenharmony_ci			} else {
12562306a36Sopenharmony_ci				memcpy(runtime->dma_area + oldptr * stride, cp,
12662306a36Sopenharmony_ci				       length * stride);
12762306a36Sopenharmony_ci			}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci			snd_pcm_stream_lock_irqsave(substream, flags);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci			dev->adev.hwptr_done_capture += length;
13262306a36Sopenharmony_ci			if (dev->adev.hwptr_done_capture >=
13362306a36Sopenharmony_ci			    runtime->buffer_size)
13462306a36Sopenharmony_ci				dev->adev.hwptr_done_capture -=
13562306a36Sopenharmony_ci				    runtime->buffer_size;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci			dev->adev.capture_transfer_done += length;
13862306a36Sopenharmony_ci			if (dev->adev.capture_transfer_done >=
13962306a36Sopenharmony_ci			    runtime->period_size) {
14062306a36Sopenharmony_ci				dev->adev.capture_transfer_done -=
14162306a36Sopenharmony_ci				    runtime->period_size;
14262306a36Sopenharmony_ci				period_elapsed = 1;
14362306a36Sopenharmony_ci			}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci			snd_pcm_stream_unlock_irqrestore(substream, flags);
14662306a36Sopenharmony_ci		}
14762306a36Sopenharmony_ci		if (period_elapsed)
14862306a36Sopenharmony_ci			snd_pcm_period_elapsed(substream);
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci	urb->status = 0;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	status = usb_submit_urb(urb, GFP_ATOMIC);
15362306a36Sopenharmony_ci	if (status < 0)
15462306a36Sopenharmony_ci		dev_err(&dev->intf->dev,
15562306a36Sopenharmony_ci			"resubmit of audio urb failed (error=%i)\n",
15662306a36Sopenharmony_ci			status);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic int em28xx_init_audio_isoc(struct em28xx *dev)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	int       i, err;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	dprintk("Starting isoc transfers\n");
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	/* Start streaming */
16662306a36Sopenharmony_ci	for (i = 0; i < dev->adev.num_urb; i++) {
16762306a36Sopenharmony_ci		memset(dev->adev.transfer_buffer[i], 0x80,
16862306a36Sopenharmony_ci		       dev->adev.urb[i]->transfer_buffer_length);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci		err = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
17162306a36Sopenharmony_ci		if (err) {
17262306a36Sopenharmony_ci			dev_err(&dev->intf->dev,
17362306a36Sopenharmony_ci				"submit of audio urb failed (error=%i)\n",
17462306a36Sopenharmony_ci				err);
17562306a36Sopenharmony_ci			em28xx_deinit_isoc_audio(dev);
17662306a36Sopenharmony_ci			atomic_set(&dev->adev.stream_started, 0);
17762306a36Sopenharmony_ci			return err;
17862306a36Sopenharmony_ci		}
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	return 0;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic const struct snd_pcm_hardware snd_em28xx_hw_capture = {
18562306a36Sopenharmony_ci	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
18662306a36Sopenharmony_ci		SNDRV_PCM_INFO_MMAP           |
18762306a36Sopenharmony_ci		SNDRV_PCM_INFO_INTERLEAVED    |
18862306a36Sopenharmony_ci		SNDRV_PCM_INFO_BATCH	      |
18962306a36Sopenharmony_ci		SNDRV_PCM_INFO_MMAP_VALID,
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	.formats = SNDRV_PCM_FMTBIT_S16_LE,
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	.rates = SNDRV_PCM_RATE_48000,
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	.rate_min = 48000,
19662306a36Sopenharmony_ci	.rate_max = 48000,
19762306a36Sopenharmony_ci	.channels_min = 2,
19862306a36Sopenharmony_ci	.channels_max = 2,
19962306a36Sopenharmony_ci	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	/*
20262306a36Sopenharmony_ci	 * The period is 12.288 bytes. Allow a 10% of variation along its
20362306a36Sopenharmony_ci	 * value, in order to avoid overruns/underruns due to some clock
20462306a36Sopenharmony_ci	 * drift.
20562306a36Sopenharmony_ci	 *
20662306a36Sopenharmony_ci	 * FIXME: This period assumes 64 packets, and a 48000 PCM rate.
20762306a36Sopenharmony_ci	 * Calculate it dynamically.
20862306a36Sopenharmony_ci	 */
20962306a36Sopenharmony_ci	.period_bytes_min = 11059,
21062306a36Sopenharmony_ci	.period_bytes_max = 13516,
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	.periods_min = 2,
21362306a36Sopenharmony_ci	.periods_max = 98,		/* 12544, */
21462306a36Sopenharmony_ci};
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	struct em28xx *dev = snd_pcm_substream_chip(substream);
21962306a36Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
22062306a36Sopenharmony_ci	int nonblock, ret = 0;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	if (!dev) {
22362306a36Sopenharmony_ci		pr_err("em28xx-audio: BUG: em28xx can't find device struct. Can't proceed with open\n");
22462306a36Sopenharmony_ci		return -ENODEV;
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (dev->disconnected)
22862306a36Sopenharmony_ci		return -ENODEV;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	dprintk("opening device and trying to acquire exclusive lock\n");
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	nonblock = !!(substream->f_flags & O_NONBLOCK);
23362306a36Sopenharmony_ci	if (nonblock) {
23462306a36Sopenharmony_ci		if (!mutex_trylock(&dev->lock))
23562306a36Sopenharmony_ci			return -EAGAIN;
23662306a36Sopenharmony_ci	} else {
23762306a36Sopenharmony_ci		mutex_lock(&dev->lock);
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	runtime->hw = snd_em28xx_hw_capture;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (dev->adev.users == 0) {
24362306a36Sopenharmony_ci		if (!dev->alt || dev->is_audio_only) {
24462306a36Sopenharmony_ci			struct usb_device *udev;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci			udev = interface_to_usbdev(dev->intf);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci			if (dev->is_audio_only)
24962306a36Sopenharmony_ci				/* audio is on a separate interface */
25062306a36Sopenharmony_ci				dev->alt = 1;
25162306a36Sopenharmony_ci			else
25262306a36Sopenharmony_ci				/* audio is on the same interface as video */
25362306a36Sopenharmony_ci				dev->alt = 7;
25462306a36Sopenharmony_ci				/*
25562306a36Sopenharmony_ci				 * FIXME: The intention seems to be to select
25662306a36Sopenharmony_ci				 * the alt setting with the largest
25762306a36Sopenharmony_ci				 * wMaxPacketSize for the video endpoint.
25862306a36Sopenharmony_ci				 * At least dev->alt should be used instead, but
25962306a36Sopenharmony_ci				 * we should probably not touch it at all if it
26062306a36Sopenharmony_ci				 * is already >0, because wMaxPacketSize of the
26162306a36Sopenharmony_ci				 * audio endpoints seems to be the same for all.
26262306a36Sopenharmony_ci				 */
26362306a36Sopenharmony_ci			dprintk("changing alternate number on interface %d to %d\n",
26462306a36Sopenharmony_ci				dev->ifnum, dev->alt);
26562306a36Sopenharmony_ci			usb_set_interface(udev, dev->ifnum, dev->alt);
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		/* Sets volume, mute, etc */
26962306a36Sopenharmony_ci		dev->mute = 0;
27062306a36Sopenharmony_ci		ret = em28xx_audio_analog_set(dev);
27162306a36Sopenharmony_ci		if (ret < 0)
27262306a36Sopenharmony_ci			goto err;
27362306a36Sopenharmony_ci	}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	kref_get(&dev->ref);
27662306a36Sopenharmony_ci	dev->adev.users++;
27762306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	/* Dynamically adjust the period size */
28062306a36Sopenharmony_ci	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
28162306a36Sopenharmony_ci	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
28262306a36Sopenharmony_ci				     dev->adev.period * 95 / 100,
28362306a36Sopenharmony_ci				     dev->adev.period * 105 / 100);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	dev->adev.capture_pcm_substream = substream;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return 0;
28862306a36Sopenharmony_cierr:
28962306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	dev_err(&dev->intf->dev,
29262306a36Sopenharmony_ci		"Error while configuring em28xx mixer\n");
29362306a36Sopenharmony_ci	return ret;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct em28xx *dev = snd_pcm_substream_chip(substream);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	dprintk("closing device\n");
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	dev->mute = 1;
30362306a36Sopenharmony_ci	mutex_lock(&dev->lock);
30462306a36Sopenharmony_ci	dev->adev.users--;
30562306a36Sopenharmony_ci	if (atomic_read(&dev->adev.stream_started) > 0) {
30662306a36Sopenharmony_ci		atomic_set(&dev->adev.stream_started, 0);
30762306a36Sopenharmony_ci		schedule_work(&dev->adev.wq_trigger);
30862306a36Sopenharmony_ci	}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	em28xx_audio_analog_set(dev);
31162306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
31262306a36Sopenharmony_ci	kref_put(&dev->ref, em28xx_free_device);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	return 0;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic int snd_em28xx_prepare(struct snd_pcm_substream *substream)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	struct em28xx *dev = snd_pcm_substream_chip(substream);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (dev->disconnected)
32262306a36Sopenharmony_ci		return -ENODEV;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	dev->adev.hwptr_done_capture = 0;
32562306a36Sopenharmony_ci	dev->adev.capture_transfer_done = 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	return 0;
32862306a36Sopenharmony_ci}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_cistatic void audio_trigger(struct work_struct *work)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	struct em28xx_audio *adev =
33362306a36Sopenharmony_ci			    container_of(work, struct em28xx_audio, wq_trigger);
33462306a36Sopenharmony_ci	struct em28xx *dev = container_of(adev, struct em28xx, adev);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (atomic_read(&adev->stream_started)) {
33762306a36Sopenharmony_ci		dprintk("starting capture");
33862306a36Sopenharmony_ci		em28xx_init_audio_isoc(dev);
33962306a36Sopenharmony_ci	} else {
34062306a36Sopenharmony_ci		dprintk("stopping capture");
34162306a36Sopenharmony_ci		em28xx_deinit_isoc_audio(dev);
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
34662306a36Sopenharmony_ci				      int cmd)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	struct em28xx *dev = snd_pcm_substream_chip(substream);
34962306a36Sopenharmony_ci	int retval = 0;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	if (dev->disconnected)
35262306a36Sopenharmony_ci		return -ENODEV;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	switch (cmd) {
35562306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
35662306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
35762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
35862306a36Sopenharmony_ci		atomic_set(&dev->adev.stream_started, 1);
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
36162306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
36262306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
36362306a36Sopenharmony_ci		atomic_set(&dev->adev.stream_started, 0);
36462306a36Sopenharmony_ci		break;
36562306a36Sopenharmony_ci	default:
36662306a36Sopenharmony_ci		retval = -EINVAL;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci	schedule_work(&dev->adev.wq_trigger);
36962306a36Sopenharmony_ci	return retval;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
37362306a36Sopenharmony_ci						    *substream)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	unsigned long flags;
37662306a36Sopenharmony_ci	struct em28xx *dev;
37762306a36Sopenharmony_ci	snd_pcm_uframes_t hwptr_done;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	dev = snd_pcm_substream_chip(substream);
38062306a36Sopenharmony_ci	if (dev->disconnected)
38162306a36Sopenharmony_ci		return SNDRV_PCM_POS_XRUN;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	spin_lock_irqsave(&dev->adev.slock, flags);
38462306a36Sopenharmony_ci	hwptr_done = dev->adev.hwptr_done_capture;
38562306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->adev.slock, flags);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	return hwptr_done;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/*
39162306a36Sopenharmony_ci * AC97 volume control support
39262306a36Sopenharmony_ci */
39362306a36Sopenharmony_cistatic int em28xx_vol_info(struct snd_kcontrol *kcontrol,
39462306a36Sopenharmony_ci			   struct snd_ctl_elem_info *info)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	if (dev->disconnected)
39962306a36Sopenharmony_ci		return -ENODEV;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
40262306a36Sopenharmony_ci	info->count = 2;
40362306a36Sopenharmony_ci	info->value.integer.min = 0;
40462306a36Sopenharmony_ci	info->value.integer.max = 0x1f;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	return 0;
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic int em28xx_vol_put(struct snd_kcontrol *kcontrol,
41062306a36Sopenharmony_ci			  struct snd_ctl_elem_value *value)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
41362306a36Sopenharmony_ci	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
41462306a36Sopenharmony_ci	u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
41562306a36Sopenharmony_ci		  (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
41662306a36Sopenharmony_ci	int nonblock = 0;
41762306a36Sopenharmony_ci	int rc;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (dev->disconnected)
42062306a36Sopenharmony_ci		return -ENODEV;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	if (substream)
42362306a36Sopenharmony_ci		nonblock = !!(substream->f_flags & O_NONBLOCK);
42462306a36Sopenharmony_ci	if (nonblock) {
42562306a36Sopenharmony_ci		if (!mutex_trylock(&dev->lock))
42662306a36Sopenharmony_ci			return -EAGAIN;
42762306a36Sopenharmony_ci	} else {
42862306a36Sopenharmony_ci		mutex_lock(&dev->lock);
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci	rc = em28xx_read_ac97(dev, kcontrol->private_value);
43162306a36Sopenharmony_ci	if (rc < 0)
43262306a36Sopenharmony_ci		goto err;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	val |= rc & 0x8000;	/* Preserve the mute flag */
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
43762306a36Sopenharmony_ci	if (rc < 0)
43862306a36Sopenharmony_ci		goto err;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
44162306a36Sopenharmony_ci		(val & 0x8000) ? "muted " : "",
44262306a36Sopenharmony_ci		0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
44362306a36Sopenharmony_ci		val, (int)kcontrol->private_value);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_cierr:
44662306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
44762306a36Sopenharmony_ci	return rc;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic int em28xx_vol_get(struct snd_kcontrol *kcontrol,
45162306a36Sopenharmony_ci			  struct snd_ctl_elem_value *value)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
45462306a36Sopenharmony_ci	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
45562306a36Sopenharmony_ci	int nonblock = 0;
45662306a36Sopenharmony_ci	int val;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	if (dev->disconnected)
45962306a36Sopenharmony_ci		return -ENODEV;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	if (substream)
46262306a36Sopenharmony_ci		nonblock = !!(substream->f_flags & O_NONBLOCK);
46362306a36Sopenharmony_ci	if (nonblock) {
46462306a36Sopenharmony_ci		if (!mutex_trylock(&dev->lock))
46562306a36Sopenharmony_ci			return -EAGAIN;
46662306a36Sopenharmony_ci	} else {
46762306a36Sopenharmony_ci		mutex_lock(&dev->lock);
46862306a36Sopenharmony_ci	}
46962306a36Sopenharmony_ci	val = em28xx_read_ac97(dev, kcontrol->private_value);
47062306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
47162306a36Sopenharmony_ci	if (val < 0)
47262306a36Sopenharmony_ci		return val;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
47562306a36Sopenharmony_ci		(val & 0x8000) ? "muted " : "",
47662306a36Sopenharmony_ci		0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
47762306a36Sopenharmony_ci		val, (int)kcontrol->private_value);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	value->value.integer.value[0] = 0x1f - (val & 0x1f);
48062306a36Sopenharmony_ci	value->value.integer.value[1] = 0x1f - ((val >> 8) & 0x1f);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	return 0;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
48662306a36Sopenharmony_ci			       struct snd_ctl_elem_value *value)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
48962306a36Sopenharmony_ci	u16 val = value->value.integer.value[0];
49062306a36Sopenharmony_ci	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
49162306a36Sopenharmony_ci	int nonblock = 0;
49262306a36Sopenharmony_ci	int rc;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	if (dev->disconnected)
49562306a36Sopenharmony_ci		return -ENODEV;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (substream)
49862306a36Sopenharmony_ci		nonblock = !!(substream->f_flags & O_NONBLOCK);
49962306a36Sopenharmony_ci	if (nonblock) {
50062306a36Sopenharmony_ci		if (!mutex_trylock(&dev->lock))
50162306a36Sopenharmony_ci			return -EAGAIN;
50262306a36Sopenharmony_ci	} else {
50362306a36Sopenharmony_ci		mutex_lock(&dev->lock);
50462306a36Sopenharmony_ci	}
50562306a36Sopenharmony_ci	rc = em28xx_read_ac97(dev, kcontrol->private_value);
50662306a36Sopenharmony_ci	if (rc < 0)
50762306a36Sopenharmony_ci		goto err;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	if (val)
51062306a36Sopenharmony_ci		rc &= 0x1f1f;
51162306a36Sopenharmony_ci	else
51262306a36Sopenharmony_ci		rc |= 0x8000;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
51562306a36Sopenharmony_ci	if (rc < 0)
51662306a36Sopenharmony_ci		goto err;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
51962306a36Sopenharmony_ci		(val & 0x8000) ? "muted " : "",
52062306a36Sopenharmony_ci		0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
52162306a36Sopenharmony_ci		val, (int)kcontrol->private_value);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cierr:
52462306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
52562306a36Sopenharmony_ci	return rc;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
52962306a36Sopenharmony_ci			       struct snd_ctl_elem_value *value)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
53262306a36Sopenharmony_ci	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
53362306a36Sopenharmony_ci	int nonblock = 0;
53462306a36Sopenharmony_ci	int val;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (dev->disconnected)
53762306a36Sopenharmony_ci		return -ENODEV;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	if (substream)
54062306a36Sopenharmony_ci		nonblock = !!(substream->f_flags & O_NONBLOCK);
54162306a36Sopenharmony_ci	if (nonblock) {
54262306a36Sopenharmony_ci		if (!mutex_trylock(&dev->lock))
54362306a36Sopenharmony_ci			return -EAGAIN;
54462306a36Sopenharmony_ci	} else {
54562306a36Sopenharmony_ci		mutex_lock(&dev->lock);
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci	val = em28xx_read_ac97(dev, kcontrol->private_value);
54862306a36Sopenharmony_ci	mutex_unlock(&dev->lock);
54962306a36Sopenharmony_ci	if (val < 0)
55062306a36Sopenharmony_ci		return val;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	if (val & 0x8000)
55362306a36Sopenharmony_ci		value->value.integer.value[0] = 0;
55462306a36Sopenharmony_ci	else
55562306a36Sopenharmony_ci		value->value.integer.value[0] = 1;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
55862306a36Sopenharmony_ci		(val & 0x8000) ? "muted " : "",
55962306a36Sopenharmony_ci		0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
56062306a36Sopenharmony_ci		val, (int)kcontrol->private_value);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	return 0;
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_cistatic int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
56862306a36Sopenharmony_ci			   char *name, int id)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	int err;
57162306a36Sopenharmony_ci	char ctl_name[44];
57262306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
57362306a36Sopenharmony_ci	struct snd_kcontrol_new tmp;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	memset(&tmp, 0, sizeof(tmp));
57662306a36Sopenharmony_ci	tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
57762306a36Sopenharmony_ci	tmp.private_value = id;
57862306a36Sopenharmony_ci	tmp.name  = ctl_name;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	/* Add Mute Control */
58162306a36Sopenharmony_ci	sprintf(ctl_name, "%s Switch", name);
58262306a36Sopenharmony_ci	tmp.get  = em28xx_vol_get_mute;
58362306a36Sopenharmony_ci	tmp.put  = em28xx_vol_put_mute;
58462306a36Sopenharmony_ci	tmp.info = snd_ctl_boolean_mono_info;
58562306a36Sopenharmony_ci	kctl = snd_ctl_new1(&tmp, dev);
58662306a36Sopenharmony_ci	err = snd_ctl_add(card, kctl);
58762306a36Sopenharmony_ci	if (err < 0)
58862306a36Sopenharmony_ci		return err;
58962306a36Sopenharmony_ci	dprintk("Added control %s for ac97 volume control 0x%04x\n",
59062306a36Sopenharmony_ci		ctl_name, id);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	memset(&tmp, 0, sizeof(tmp));
59362306a36Sopenharmony_ci	tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
59462306a36Sopenharmony_ci	tmp.private_value = id;
59562306a36Sopenharmony_ci	tmp.name  = ctl_name;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	/* Add Volume Control */
59862306a36Sopenharmony_ci	sprintf(ctl_name, "%s Volume", name);
59962306a36Sopenharmony_ci	tmp.get   = em28xx_vol_get;
60062306a36Sopenharmony_ci	tmp.put   = em28xx_vol_put;
60162306a36Sopenharmony_ci	tmp.info  = em28xx_vol_info;
60262306a36Sopenharmony_ci	tmp.tlv.p = em28xx_db_scale;
60362306a36Sopenharmony_ci	kctl = snd_ctl_new1(&tmp, dev);
60462306a36Sopenharmony_ci	err = snd_ctl_add(card, kctl);
60562306a36Sopenharmony_ci	if (err < 0)
60662306a36Sopenharmony_ci		return err;
60762306a36Sopenharmony_ci	dprintk("Added control %s for ac97 volume control 0x%04x\n",
60862306a36Sopenharmony_ci		ctl_name, id);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	return 0;
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci/*
61462306a36Sopenharmony_ci * register/unregister code and data
61562306a36Sopenharmony_ci */
61662306a36Sopenharmony_cistatic const struct snd_pcm_ops snd_em28xx_pcm_capture = {
61762306a36Sopenharmony_ci	.open      = snd_em28xx_capture_open,
61862306a36Sopenharmony_ci	.close     = snd_em28xx_pcm_close,
61962306a36Sopenharmony_ci	.prepare   = snd_em28xx_prepare,
62062306a36Sopenharmony_ci	.trigger   = snd_em28xx_capture_trigger,
62162306a36Sopenharmony_ci	.pointer   = snd_em28xx_capture_pointer,
62262306a36Sopenharmony_ci};
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic void em28xx_audio_free_urb(struct em28xx *dev)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(dev->intf);
62762306a36Sopenharmony_ci	int i;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	for (i = 0; i < dev->adev.num_urb; i++) {
63062306a36Sopenharmony_ci		struct urb *urb = dev->adev.urb[i];
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci		if (!urb)
63362306a36Sopenharmony_ci			continue;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		usb_free_coherent(udev, urb->transfer_buffer_length,
63662306a36Sopenharmony_ci				  dev->adev.transfer_buffer[i],
63762306a36Sopenharmony_ci				  urb->transfer_dma);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci		usb_free_urb(urb);
64062306a36Sopenharmony_ci	}
64162306a36Sopenharmony_ci	kfree(dev->adev.urb);
64262306a36Sopenharmony_ci	kfree(dev->adev.transfer_buffer);
64362306a36Sopenharmony_ci	dev->adev.num_urb = 0;
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
64762306a36Sopenharmony_cistatic int em28xx_audio_ep_packet_size(struct usb_device *udev,
64862306a36Sopenharmony_ci				       struct usb_endpoint_descriptor *e)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	int size = le16_to_cpu(e->wMaxPacketSize);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (udev->speed == USB_SPEED_HIGH)
65362306a36Sopenharmony_ci		return (size & 0x7ff) *  (1 + (((size) >> 11) & 0x03));
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	return size & 0x7ff;
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic int em28xx_audio_urb_init(struct em28xx *dev)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	struct usb_interface *intf;
66162306a36Sopenharmony_ci	struct usb_endpoint_descriptor *e, *ep = NULL;
66262306a36Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(dev->intf);
66362306a36Sopenharmony_ci	int                 i, ep_size, interval, num_urb, npackets;
66462306a36Sopenharmony_ci	int		    urb_size, bytes_per_transfer;
66562306a36Sopenharmony_ci	u8 alt;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	if (dev->ifnum)
66862306a36Sopenharmony_ci		alt = 1;
66962306a36Sopenharmony_ci	else
67062306a36Sopenharmony_ci		alt = 7;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	intf = usb_ifnum_to_if(udev, dev->ifnum);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	if (intf->num_altsetting <= alt) {
67562306a36Sopenharmony_ci		dev_err(&dev->intf->dev, "alt %d doesn't exist on interface %d\n",
67662306a36Sopenharmony_ci			dev->ifnum, alt);
67762306a36Sopenharmony_ci		return -ENODEV;
67862306a36Sopenharmony_ci	}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	for (i = 0; i < intf->altsetting[alt].desc.bNumEndpoints; i++) {
68162306a36Sopenharmony_ci		e = &intf->altsetting[alt].endpoint[i].desc;
68262306a36Sopenharmony_ci		if (!usb_endpoint_dir_in(e))
68362306a36Sopenharmony_ci			continue;
68462306a36Sopenharmony_ci		if (e->bEndpointAddress == EM28XX_EP_AUDIO) {
68562306a36Sopenharmony_ci			ep = e;
68662306a36Sopenharmony_ci			break;
68762306a36Sopenharmony_ci		}
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	if (!ep) {
69162306a36Sopenharmony_ci		dev_err(&dev->intf->dev, "Couldn't find an audio endpoint");
69262306a36Sopenharmony_ci		return -ENODEV;
69362306a36Sopenharmony_ci	}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	ep_size = em28xx_audio_ep_packet_size(udev, ep);
69662306a36Sopenharmony_ci	interval = 1 << (ep->bInterval - 1);
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	dev_info(&dev->intf->dev,
69962306a36Sopenharmony_ci		 "Endpoint 0x%02x %s on intf %d alt %d interval = %d, size %d\n",
70062306a36Sopenharmony_ci		 EM28XX_EP_AUDIO, usb_speed_string(udev->speed),
70162306a36Sopenharmony_ci		 dev->ifnum, alt, interval, ep_size);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	/* Calculate the number and size of URBs to better fit the audio samples */
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	/*
70662306a36Sopenharmony_ci	 * Estimate the number of bytes per DMA transfer.
70762306a36Sopenharmony_ci	 *
70862306a36Sopenharmony_ci	 * This is given by the bit rate (for now, only 48000 Hz) multiplied
70962306a36Sopenharmony_ci	 * by 2 channels and 2 bytes/sample divided by the number of microframe
71062306a36Sopenharmony_ci	 * intervals and by the microframe rate (125 us)
71162306a36Sopenharmony_ci	 */
71262306a36Sopenharmony_ci	bytes_per_transfer = DIV_ROUND_UP(48000 * 2 * 2, 125 * interval);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	/*
71562306a36Sopenharmony_ci	 * Estimate the number of transfer URBs. Don't let it go past the
71662306a36Sopenharmony_ci	 * maximum number of URBs that is known to be supported by the device.
71762306a36Sopenharmony_ci	 */
71862306a36Sopenharmony_ci	num_urb = DIV_ROUND_UP(bytes_per_transfer, ep_size);
71962306a36Sopenharmony_ci	if (num_urb > EM28XX_MAX_AUDIO_BUFS)
72062306a36Sopenharmony_ci		num_urb = EM28XX_MAX_AUDIO_BUFS;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	/*
72362306a36Sopenharmony_ci	 * Now that we know the number of bytes per transfer and the number of
72462306a36Sopenharmony_ci	 * URBs, estimate the typical size of an URB, in order to adjust the
72562306a36Sopenharmony_ci	 * minimal number of packets.
72662306a36Sopenharmony_ci	 */
72762306a36Sopenharmony_ci	urb_size = bytes_per_transfer / num_urb;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	/*
73062306a36Sopenharmony_ci	 * Now, calculate the amount of audio packets to be filled on each
73162306a36Sopenharmony_ci	 * URB. In order to preserve the old behaviour, use a minimal
73262306a36Sopenharmony_ci	 * threshold for this value.
73362306a36Sopenharmony_ci	 */
73462306a36Sopenharmony_ci	npackets = EM28XX_MIN_AUDIO_PACKETS;
73562306a36Sopenharmony_ci	if (urb_size > ep_size * npackets)
73662306a36Sopenharmony_ci		npackets = DIV_ROUND_UP(urb_size, ep_size);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	dev_info(&dev->intf->dev,
73962306a36Sopenharmony_ci		 "Number of URBs: %d, with %d packets and %d size\n",
74062306a36Sopenharmony_ci		 num_urb, npackets, urb_size);
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	/* Estimate the bytes per period */
74362306a36Sopenharmony_ci	dev->adev.period = urb_size * npackets;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	/* Allocate space to store the number of URBs to be used */
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	dev->adev.transfer_buffer = kcalloc(num_urb,
74862306a36Sopenharmony_ci					    sizeof(*dev->adev.transfer_buffer),
74962306a36Sopenharmony_ci					    GFP_KERNEL);
75062306a36Sopenharmony_ci	if (!dev->adev.transfer_buffer)
75162306a36Sopenharmony_ci		return -ENOMEM;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_KERNEL);
75462306a36Sopenharmony_ci	if (!dev->adev.urb) {
75562306a36Sopenharmony_ci		kfree(dev->adev.transfer_buffer);
75662306a36Sopenharmony_ci		return -ENOMEM;
75762306a36Sopenharmony_ci	}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	/* Alloc memory for each URB and for each transfer buffer */
76062306a36Sopenharmony_ci	dev->adev.num_urb = num_urb;
76162306a36Sopenharmony_ci	for (i = 0; i < num_urb; i++) {
76262306a36Sopenharmony_ci		struct urb *urb;
76362306a36Sopenharmony_ci		int j, k;
76462306a36Sopenharmony_ci		void *buf;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci		urb = usb_alloc_urb(npackets, GFP_KERNEL);
76762306a36Sopenharmony_ci		if (!urb) {
76862306a36Sopenharmony_ci			em28xx_audio_free_urb(dev);
76962306a36Sopenharmony_ci			return -ENOMEM;
77062306a36Sopenharmony_ci		}
77162306a36Sopenharmony_ci		dev->adev.urb[i] = urb;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci		buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_KERNEL,
77462306a36Sopenharmony_ci					 &urb->transfer_dma);
77562306a36Sopenharmony_ci		if (!buf) {
77662306a36Sopenharmony_ci			dev_err(&dev->intf->dev,
77762306a36Sopenharmony_ci				"usb_alloc_coherent failed!\n");
77862306a36Sopenharmony_ci			em28xx_audio_free_urb(dev);
77962306a36Sopenharmony_ci			return -ENOMEM;
78062306a36Sopenharmony_ci		}
78162306a36Sopenharmony_ci		dev->adev.transfer_buffer[i] = buf;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci		urb->dev = udev;
78462306a36Sopenharmony_ci		urb->context = dev;
78562306a36Sopenharmony_ci		urb->pipe = usb_rcvisocpipe(udev, EM28XX_EP_AUDIO);
78662306a36Sopenharmony_ci		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
78762306a36Sopenharmony_ci		urb->transfer_buffer = buf;
78862306a36Sopenharmony_ci		urb->interval = interval;
78962306a36Sopenharmony_ci		urb->complete = em28xx_audio_isocirq;
79062306a36Sopenharmony_ci		urb->number_of_packets = npackets;
79162306a36Sopenharmony_ci		urb->transfer_buffer_length = ep_size * npackets;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci		for (j = k = 0; j < npackets; j++, k += ep_size) {
79462306a36Sopenharmony_ci			urb->iso_frame_desc[j].offset = k;
79562306a36Sopenharmony_ci			urb->iso_frame_desc[j].length = ep_size;
79662306a36Sopenharmony_ci		}
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	return 0;
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_cistatic int em28xx_audio_init(struct em28xx *dev)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	struct em28xx_audio *adev = &dev->adev;
80562306a36Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(dev->intf);
80662306a36Sopenharmony_ci	struct snd_pcm      *pcm;
80762306a36Sopenharmony_ci	struct snd_card     *card;
80862306a36Sopenharmony_ci	static int          devnr;
80962306a36Sopenharmony_ci	int		    err;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) {
81262306a36Sopenharmony_ci		/*
81362306a36Sopenharmony_ci		 * This device does not support the extension (in this case
81462306a36Sopenharmony_ci		 * the device is expecting the snd-usb-audio module or
81562306a36Sopenharmony_ci		 * doesn't have analog audio support at all)
81662306a36Sopenharmony_ci		 */
81762306a36Sopenharmony_ci		return 0;
81862306a36Sopenharmony_ci	}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	dev_info(&dev->intf->dev, "Binding audio extension\n");
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	kref_get(&dev->ref);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	dev_info(&dev->intf->dev,
82562306a36Sopenharmony_ci		 "em28xx-audio.c: Copyright (C) 2006 Markus Rechberger\n");
82662306a36Sopenharmony_ci	dev_info(&dev->intf->dev,
82762306a36Sopenharmony_ci		 "em28xx-audio.c: Copyright (C) 2007-2016 Mauro Carvalho Chehab\n");
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	err = snd_card_new(&dev->intf->dev, index[devnr], "Em28xx Audio",
83062306a36Sopenharmony_ci			   THIS_MODULE, 0, &card);
83162306a36Sopenharmony_ci	if (err < 0)
83262306a36Sopenharmony_ci		return err;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	spin_lock_init(&adev->slock);
83562306a36Sopenharmony_ci	adev->sndcard = card;
83662306a36Sopenharmony_ci	adev->udev = udev;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
83962306a36Sopenharmony_ci	if (err < 0)
84062306a36Sopenharmony_ci		goto card_free;
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
84362306a36Sopenharmony_ci	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
84462306a36Sopenharmony_ci	pcm->info_flags = 0;
84562306a36Sopenharmony_ci	pcm->private_data = dev;
84662306a36Sopenharmony_ci	strscpy(pcm->name, "Empia 28xx Capture", sizeof(pcm->name));
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	strscpy(card->driver, "Em28xx-Audio", sizeof(card->driver));
84962306a36Sopenharmony_ci	strscpy(card->shortname, "Em28xx Audio", sizeof(card->shortname));
85062306a36Sopenharmony_ci	strscpy(card->longname, "Empia Em28xx Audio", sizeof(card->longname));
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	INIT_WORK(&adev->wq_trigger, audio_trigger);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
85562306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
85662306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
85762306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
85862306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
85962306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "CD", AC97_CD);
86062306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
86162306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
86462306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
86562306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
86662306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
86762306a36Sopenharmony_ci		em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
86862306a36Sopenharmony_ci	}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	err = em28xx_audio_urb_init(dev);
87162306a36Sopenharmony_ci	if (err)
87262306a36Sopenharmony_ci		goto card_free;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	err = snd_card_register(card);
87562306a36Sopenharmony_ci	if (err < 0)
87662306a36Sopenharmony_ci		goto urb_free;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	dev_info(&dev->intf->dev, "Audio extension successfully initialized\n");
87962306a36Sopenharmony_ci	return 0;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ciurb_free:
88262306a36Sopenharmony_ci	em28xx_audio_free_urb(dev);
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_cicard_free:
88562306a36Sopenharmony_ci	snd_card_free(card);
88662306a36Sopenharmony_ci	adev->sndcard = NULL;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	return err;
88962306a36Sopenharmony_ci}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic int em28xx_audio_fini(struct em28xx *dev)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	if (!dev)
89462306a36Sopenharmony_ci		return 0;
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) {
89762306a36Sopenharmony_ci		/*
89862306a36Sopenharmony_ci		 * This device does not support the extension (in this case
89962306a36Sopenharmony_ci		 * the device is expecting the snd-usb-audio module or
90062306a36Sopenharmony_ci		 * doesn't have analog audio support at all)
90162306a36Sopenharmony_ci		 */
90262306a36Sopenharmony_ci		return 0;
90362306a36Sopenharmony_ci	}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	dev_info(&dev->intf->dev, "Closing audio extension\n");
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	if (dev->adev.sndcard) {
90862306a36Sopenharmony_ci		snd_card_disconnect(dev->adev.sndcard);
90962306a36Sopenharmony_ci		flush_work(&dev->adev.wq_trigger);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci		em28xx_audio_free_urb(dev);
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci		snd_card_free(dev->adev.sndcard);
91462306a36Sopenharmony_ci		dev->adev.sndcard = NULL;
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	kref_put(&dev->ref, em28xx_free_device);
91862306a36Sopenharmony_ci	return 0;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cistatic int em28xx_audio_suspend(struct em28xx *dev)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	if (!dev)
92462306a36Sopenharmony_ci		return 0;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
92762306a36Sopenharmony_ci		return 0;
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	dev_info(&dev->intf->dev, "Suspending audio extension\n");
93062306a36Sopenharmony_ci	em28xx_deinit_isoc_audio(dev);
93162306a36Sopenharmony_ci	atomic_set(&dev->adev.stream_started, 0);
93262306a36Sopenharmony_ci	return 0;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_cistatic int em28xx_audio_resume(struct em28xx *dev)
93662306a36Sopenharmony_ci{
93762306a36Sopenharmony_ci	if (!dev)
93862306a36Sopenharmony_ci		return 0;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
94162306a36Sopenharmony_ci		return 0;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	dev_info(&dev->intf->dev, "Resuming audio extension\n");
94462306a36Sopenharmony_ci	/* Nothing to do other than schedule_work() ?? */
94562306a36Sopenharmony_ci	schedule_work(&dev->adev.wq_trigger);
94662306a36Sopenharmony_ci	return 0;
94762306a36Sopenharmony_ci}
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_cistatic struct em28xx_ops audio_ops = {
95062306a36Sopenharmony_ci	.id   = EM28XX_AUDIO,
95162306a36Sopenharmony_ci	.name = "Em28xx Audio Extension",
95262306a36Sopenharmony_ci	.init = em28xx_audio_init,
95362306a36Sopenharmony_ci	.fini = em28xx_audio_fini,
95462306a36Sopenharmony_ci	.suspend = em28xx_audio_suspend,
95562306a36Sopenharmony_ci	.resume = em28xx_audio_resume,
95662306a36Sopenharmony_ci};
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_cistatic int __init em28xx_alsa_register(void)
95962306a36Sopenharmony_ci{
96062306a36Sopenharmony_ci	return em28xx_register_extension(&audio_ops);
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistatic void __exit em28xx_alsa_unregister(void)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	em28xx_unregister_extension(&audio_ops);
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
96962306a36Sopenharmony_ciMODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
97062306a36Sopenharmony_ciMODULE_AUTHOR("Mauro Carvalho Chehab");
97162306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC " - audio interface");
97262306a36Sopenharmony_ciMODULE_VERSION(EM28XX_VERSION);
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cimodule_init(em28xx_alsa_register);
97562306a36Sopenharmony_cimodule_exit(em28xx_alsa_unregister);
976