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