···22242224 Quirk alias list, pass strings like ``0123abcd:5678beef``, which22252225 applies the existing quirk for the device 5678:beef to a new22262226 device 0123:abcd.22272227+use_vmalloc22282228+ Use vmalloc() for allocations of the PCM buffers (default: yes).22292229+ For architectures with non-coherent memory like ARM or MIPS, the22302230+ mmap access may give inconsistent results with vmalloc'ed22312231+ buffers. If mmap is used on such architectures, turn off this22322232+ option, so that the DMA-coherent buffers are allocated and used22332233+ instead.2227223422282235This module supports multiple devices, autoprobe and hotplugging.22292236
+2
Documentation/sound/hd-audio/models.rst
···263263 HP dock support264264mute-led-gpio265265 Mute LED control via GPIO266266+hp-mic-fix267267+ Fix for headset mic pin on HP boxes266268267269STAC9200268270========
+7
MAINTAINERS
···1549415494F: arch/x86/xen/*swiotlb*1549515495F: drivers/xen/*swiotlb*15496154961549715497+XEN SOUND FRONTEND DRIVER1549815498+M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>1549915499+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)1550015500+L: alsa-devel@alsa-project.org (moderated for non-subscribers)1550115501+S: Supported1550215502+F: sound/xen/*1550315503+1549715504XFS FILESYSTEM1549815505M: Darrick J. Wong <darrick.wong@oracle.com>1549915506M: linux-xfs@vger.kernel.org
···5151 */5252enum snd_device_type {5353 SNDRV_DEV_LOWLEVEL,5454- SNDRV_DEV_CONTROL,5554 SNDRV_DEV_INFO,5655 SNDRV_DEV_BUS,5756 SNDRV_DEV_CODEC,···6162 SNDRV_DEV_SEQUENCER,6263 SNDRV_DEV_HWDEP,6364 SNDRV_DEV_JACK,6565+ SNDRV_DEV_CONTROL, /* NOTE: this must be the last one */6466};65676668enum snd_device_state {
···4242#define SNDRV_CTL_TLVD_LENGTH(...) \4343 ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))44444545+/* Accessor offsets for TLV data items */4646+#define SNDRV_CTL_TLVO_TYPE 04747+#define SNDRV_CTL_TLVO_LEN 14848+4549#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \4650 SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)4751#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \···6561 SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \6662 }67636464+/* Accessor offsets for min, mute and step items in dB scale type TLV */6565+#define SNDRV_CTL_TLVO_DB_SCALE_MIN 26666+#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 36767+6868/* dB scale specified with min/max values instead of step */6969#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \7070 SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))···8375 SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \8476 }85777878+/* Accessor offsets for min, max items in db-minmax types of TLV. */7979+#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 28080+#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 38181+8682/* linear volume between min_dB and max_dB (.01dB unit) */8783#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \8884 SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))···9482 unsigned int name[] = { \9583 SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \9684 }8585+8686+/* Accessor offsets for min, max items in db-linear type of TLV. */8787+#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 28888+#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 397899890/* dB range container:9991 * Items in dB range container must be ordered by their values and by their
···9999 cond_resched();100100}101101102102+#define PCM_LOCK_DEFAULT 0103103+#define PCM_LOCK_IRQ 1104104+#define PCM_LOCK_IRQSAVE 2105105+106106+static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,107107+ unsigned int mode)108108+{109109+ unsigned long flags = 0;110110+ if (substream->pcm->nonatomic) {111111+ down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);112112+ mutex_lock(&substream->self_group.mutex);113113+ } else {114114+ switch (mode) {115115+ case PCM_LOCK_DEFAULT:116116+ read_lock(&snd_pcm_link_rwlock);117117+ break;118118+ case PCM_LOCK_IRQ:119119+ read_lock_irq(&snd_pcm_link_rwlock);120120+ break;121121+ case PCM_LOCK_IRQSAVE:122122+ read_lock_irqsave(&snd_pcm_link_rwlock, flags);123123+ break;124124+ }125125+ spin_lock(&substream->self_group.lock);126126+ }127127+ return flags;128128+}129129+130130+static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,131131+ unsigned int mode, unsigned long flags)132132+{133133+ if (substream->pcm->nonatomic) {134134+ mutex_unlock(&substream->self_group.mutex);135135+ up_read(&snd_pcm_link_rwsem);136136+ } else {137137+ spin_unlock(&substream->self_group.lock);138138+139139+ switch (mode) {140140+ case PCM_LOCK_DEFAULT:141141+ read_unlock(&snd_pcm_link_rwlock);142142+ break;143143+ case PCM_LOCK_IRQ:144144+ read_unlock_irq(&snd_pcm_link_rwlock);145145+ break;146146+ case PCM_LOCK_IRQSAVE:147147+ read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);148148+ break;149149+ }150150+ }151151+}152152+102153/**103154 * snd_pcm_stream_lock - Lock the PCM stream104155 * @substream: PCM substream···160109 */161110void snd_pcm_stream_lock(struct snd_pcm_substream *substream)162111{163163- if (substream->pcm->nonatomic) {164164- down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);165165- mutex_lock(&substream->self_group.mutex);166166- } else {167167- read_lock(&snd_pcm_link_rwlock);168168- spin_lock(&substream->self_group.lock);169169- }112112+ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);170113}171114EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);172115···172127 */173128void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)174129{175175- if (substream->pcm->nonatomic) {176176- mutex_unlock(&substream->self_group.mutex);177177- up_read(&snd_pcm_link_rwsem);178178- } else {179179- spin_unlock(&substream->self_group.lock);180180- read_unlock(&snd_pcm_link_rwlock);181181- }130130+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);182131}183132EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);184133···186147 */187148void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)188149{189189- if (!substream->pcm->nonatomic)190190- local_irq_disable();191191- snd_pcm_stream_lock(substream);150150+ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);192151}193152EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);194153···198161 */199162void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)200163{201201- snd_pcm_stream_unlock(substream);202202- if (!substream->pcm->nonatomic)203203- local_irq_enable();164164+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);204165}205166EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);206167207168unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)208169{209209- unsigned long flags = 0;210210- if (!substream->pcm->nonatomic)211211- local_irq_save(flags);212212- snd_pcm_stream_lock(substream);213213- return flags;170170+ return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);214171}215172EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);216173···218187void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,219188 unsigned long flags)220189{221221- snd_pcm_stream_unlock(substream);222222- if (!substream->pcm->nonatomic)223223- local_irq_restore(flags);190190+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);224191}225192EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);226193···886857 return err;887858}888859860860+static inline snd_pcm_uframes_t861861+snd_pcm_calc_delay(struct snd_pcm_substream *substream)862862+{863863+ snd_pcm_uframes_t delay;864864+865865+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)866866+ delay = snd_pcm_playback_hw_avail(substream->runtime);867867+ else868868+ delay = snd_pcm_capture_avail(substream->runtime);869869+ return delay + substream->runtime->delay;870870+}871871+889872int snd_pcm_status(struct snd_pcm_substream *substream,890873 struct snd_pcm_status *status)891874{···949908 _tstamp_end:950909 status->appl_ptr = runtime->control->appl_ptr;951910 status->hw_ptr = runtime->status->hw_ptr;952952- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {953953- status->avail = snd_pcm_playback_avail(runtime);954954- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||955955- runtime->status->state == SNDRV_PCM_STATE_DRAINING) {956956- status->delay = runtime->buffer_size - status->avail;957957- status->delay += runtime->delay;958958- } else959959- status->delay = 0;960960- } else {961961- status->avail = snd_pcm_capture_avail(runtime);962962- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)963963- status->delay = status->avail + runtime->delay;964964- else965965- status->delay = 0;966966- }911911+ status->avail = snd_pcm_avail(substream);912912+ status->delay = snd_pcm_running(substream) ?913913+ snd_pcm_calc_delay(substream) : 0;967914 status->avail_max = runtime->avail_max;968915 status->overrange = runtime->overrange;969916 runtime->avail_max = 0;···26392610 return ret < 0 ? 0 : frames;26402611}2641261226422642-static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,26432643- snd_pcm_uframes_t frames)26132613+static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,26142614+ snd_pcm_uframes_t frames)26442615{26452645- struct snd_pcm_runtime *runtime = substream->runtime;26462616 snd_pcm_sframes_t ret;2647261726482618 if (frames == 0)···26512623 ret = do_pcm_hwsync(substream);26522624 if (!ret)26532625 ret = rewind_appl_ptr(substream, frames,26542654- snd_pcm_playback_hw_avail(runtime));26262626+ snd_pcm_hw_avail(substream));26552627 snd_pcm_stream_unlock_irq(substream);26562628 return ret;26572629}2658263026592659-static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,26602660- snd_pcm_uframes_t frames)26312631+static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,26322632+ snd_pcm_uframes_t frames)26612633{26622662- struct snd_pcm_runtime *runtime = substream->runtime;26632663- snd_pcm_sframes_t ret;26642664-26652665- if (frames == 0)26662666- return 0;26672667-26682668- snd_pcm_stream_lock_irq(substream);26692669- ret = do_pcm_hwsync(substream);26702670- if (!ret)26712671- ret = rewind_appl_ptr(substream, frames,26722672- snd_pcm_capture_hw_avail(runtime));26732673- snd_pcm_stream_unlock_irq(substream);26742674- return ret;26752675-}26762676-26772677-static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,26782678- snd_pcm_uframes_t frames)26792679-{26802680- struct snd_pcm_runtime *runtime = substream->runtime;26812634 snd_pcm_sframes_t ret;2682263526832636 if (frames == 0)···26682659 ret = do_pcm_hwsync(substream);26692660 if (!ret)26702661 ret = forward_appl_ptr(substream, frames,26712671- snd_pcm_playback_avail(runtime));26722672- snd_pcm_stream_unlock_irq(substream);26732673- return ret;26742674-}26752675-26762676-static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,26772677- snd_pcm_uframes_t frames)26782678-{26792679- struct snd_pcm_runtime *runtime = substream->runtime;26802680- snd_pcm_sframes_t ret;26812681-26822682- if (frames == 0)26832683- return 0;26842684-26852685- snd_pcm_stream_lock_irq(substream);26862686- ret = do_pcm_hwsync(substream);26872687- if (!ret)26882688- ret = forward_appl_ptr(substream, frames,26892689- snd_pcm_capture_avail(runtime));26622662+ snd_pcm_avail(substream));26902663 snd_pcm_stream_unlock_irq(substream);26912664 return ret;26922665}···26862695static int snd_pcm_delay(struct snd_pcm_substream *substream,26872696 snd_pcm_sframes_t *delay)26882697{26892689- struct snd_pcm_runtime *runtime = substream->runtime;26902698 int err;26912699 snd_pcm_sframes_t n = 0;2692270026932701 snd_pcm_stream_lock_irq(substream);26942702 err = do_pcm_hwsync(substream);26952695- if (!err) {26962696- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)26972697- n = snd_pcm_playback_hw_avail(runtime);26982698- else26992699- n = snd_pcm_capture_avail(runtime);27002700- n += runtime->delay;27012701- }27032703+ if (!err)27042704+ n = snd_pcm_calc_delay(substream);27022705 snd_pcm_stream_unlock_irq(substream);27032706 if (!err)27042707 *delay = n;···28192834 return -EFAULT;28202835 if (put_user(0, _frames))28212836 return -EFAULT;28222822- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)28232823- result = snd_pcm_playback_rewind(substream, frames);28242824- else28252825- result = snd_pcm_capture_rewind(substream, frames);28372837+ result = snd_pcm_rewind(substream, frames);28262838 __put_user(result, _frames);28272839 return result < 0 ? result : 0;28282840}···28342852 return -EFAULT;28352853 if (put_user(0, _frames))28362854 return -EFAULT;28372837- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)28382838- result = snd_pcm_playback_forward(substream, frames);28392839- else28402840- result = snd_pcm_capture_forward(substream, frames);28552855+ result = snd_pcm_forward(substream, frames);28412856 __put_user(result, _frames);28422857 return result < 0 ? result : 0;28432858}···29772998 /* provided only for OSS; capture-only and no value returned */29782999 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)29793000 return -EINVAL;29802980- result = snd_pcm_capture_forward(substream, *frames);30013001+ result = snd_pcm_forward(substream, *frames);29813002 return result < 0 ? result : 0;29823003 }29833004 case SNDRV_PCM_IOCTL_HW_PARAMS:···31193140 return result;31203141}3121314231223122-static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait)31433143+static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)31233144{31243145 struct snd_pcm_file *pcm_file;31253146 struct snd_pcm_substream *substream;31263147 struct snd_pcm_runtime *runtime;31273127- __poll_t mask;31483148+ __poll_t mask, ok;31283149 snd_pcm_uframes_t avail;3129315031303151 pcm_file = file->private_data;3131315231323153 substream = pcm_file->substream;31543154+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)31553155+ ok = EPOLLOUT | EPOLLWRNORM;31563156+ else31573157+ ok = EPOLLIN | EPOLLRDNORM;31333158 if (PCM_RUNTIME_CHECK(substream))31343134- return EPOLLOUT | EPOLLWRNORM | EPOLLERR;31353135- runtime = substream->runtime;31593159+ return ok | EPOLLERR;3136316031613161+ runtime = substream->runtime;31373162 poll_wait(file, &runtime->sleep, wait);3138316331643164+ mask = 0;31393165 snd_pcm_stream_lock_irq(substream);31403140- avail = snd_pcm_playback_avail(runtime);31663166+ avail = snd_pcm_avail(substream);31413167 switch (runtime->status->state) {31423168 case SNDRV_PCM_STATE_RUNNING:31433169 case SNDRV_PCM_STATE_PREPARED:31443170 case SNDRV_PCM_STATE_PAUSED:31453145- if (avail >= runtime->control->avail_min) {31463146- mask = EPOLLOUT | EPOLLWRNORM;31473147- break;31483148- }31493149- /* Fall through */31503150- case SNDRV_PCM_STATE_DRAINING:31513151- mask = 0;31523152- break;31533153- default:31543154- mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR;31553155- break;31563156- }31573157- snd_pcm_stream_unlock_irq(substream);31583158- return mask;31593159-}31603160-31613161-static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait)31623162-{31633163- struct snd_pcm_file *pcm_file;31643164- struct snd_pcm_substream *substream;31653165- struct snd_pcm_runtime *runtime;31663166- __poll_t mask;31673167- snd_pcm_uframes_t avail;31683168-31693169- pcm_file = file->private_data;31703170-31713171- substream = pcm_file->substream;31723172- if (PCM_RUNTIME_CHECK(substream))31733173- return EPOLLIN | EPOLLRDNORM | EPOLLERR;31743174- runtime = substream->runtime;31753175-31763176- poll_wait(file, &runtime->sleep, wait);31773177-31783178- snd_pcm_stream_lock_irq(substream);31793179- avail = snd_pcm_capture_avail(runtime);31803180- switch (runtime->status->state) {31813181- case SNDRV_PCM_STATE_RUNNING:31823182- case SNDRV_PCM_STATE_PREPARED:31833183- case SNDRV_PCM_STATE_PAUSED:31843184- if (avail >= runtime->control->avail_min) {31853185- mask = EPOLLIN | EPOLLRDNORM;31863186- break;31873187- }31883188- mask = 0;31713171+ if (avail >= runtime->control->avail_min)31723172+ mask = ok;31893173 break;31903174 case SNDRV_PCM_STATE_DRAINING:31913191- if (avail > 0) {31923192- mask = EPOLLIN | EPOLLRDNORM;31933193- break;31753175+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {31763176+ mask = ok;31773177+ if (!avail)31783178+ mask |= EPOLLERR;31943179 }31953195- /* Fall through */31803180+ break;31963181 default:31973197- mask = EPOLLIN | EPOLLRDNORM | EPOLLERR;31823182+ mask = ok | EPOLLERR;31983183 break;31993184 }32003185 snd_pcm_stream_unlock_irq(substream);···36503707 .open = snd_pcm_playback_open,36513708 .release = snd_pcm_release,36523709 .llseek = no_llseek,36533653- .poll = snd_pcm_playback_poll,37103710+ .poll = snd_pcm_poll,36543711 .unlocked_ioctl = snd_pcm_ioctl,36553712 .compat_ioctl = snd_pcm_ioctl_compat,36563713 .mmap = snd_pcm_mmap,···36643721 .open = snd_pcm_capture_open,36653722 .release = snd_pcm_release,36663723 .llseek = no_llseek,36673667- .poll = snd_pcm_capture_poll,37243724+ .poll = snd_pcm_poll,36683725 .unlocked_ioctl = snd_pcm_ioctl,36693726 .compat_ioctl = snd_pcm_ioctl_compat,36703727 .mmap = snd_pcm_mmap,
+1-1
sound/core/seq/seq_ports.c
···669669 /* Set up the port */670670 memset(&portinfo, 0, sizeof(portinfo));671671 portinfo.addr.client = client;672672- strlcpy(portinfo.name, portname ? portname : "Unamed port",672672+ strlcpy(portinfo.name, portname ? portname : "Unnamed port",673673 sizeof(portinfo.name));674674675675 portinfo.capability = cap;
+1-3
sound/core/seq/seq_timer.c
···371371372372 tmr->ticks = 1;373373 if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {374374- unsigned long r = t->hw.resolution;375375- if (! r && t->hw.c_resolution)376376- r = t->hw.c_resolution(t);374374+ unsigned long r = snd_timer_resolution(tmr->timeri);377375 if (r) {378376 tmr->ticks = (unsigned int)(1000000000uL / (r * freq));379377 if (! tmr->ticks)
+25-23
sound/core/timer.c
···427427}428428EXPORT_SYMBOL(snd_timer_close);429429430430+static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)431431+{432432+ if (timer->hw.c_resolution)433433+ return timer->hw.c_resolution(timer);434434+ else435435+ return timer->hw.resolution;436436+}437437+430438unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)431439{432440 struct snd_timer * timer;441441+ unsigned long ret = 0;442442+ unsigned long flags;433443434444 if (timeri == NULL)435445 return 0;436446 timer = timeri->timer;437447 if (timer) {438438- if (timer->hw.c_resolution)439439- return timer->hw.c_resolution(timer);440440- return timer->hw.resolution;448448+ spin_lock_irqsave(&timer->lock, flags);449449+ ret = snd_timer_hw_resolution(timer);450450+ spin_unlock_irqrestore(&timer->lock, flags);441451 }442442- return 0;452452+ return ret;443453}444454EXPORT_SYMBOL(snd_timer_resolution);445455446456static void snd_timer_notify1(struct snd_timer_instance *ti, int event)447457{448448- struct snd_timer *timer;458458+ struct snd_timer *timer = ti->timer;449459 unsigned long resolution = 0;450460 struct snd_timer_instance *ts;451461 struct timespec tstamp;···467457 if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||468458 event > SNDRV_TIMER_EVENT_PAUSE))469459 return;470470- if (event == SNDRV_TIMER_EVENT_START ||471471- event == SNDRV_TIMER_EVENT_CONTINUE)472472- resolution = snd_timer_resolution(ti);460460+ if (timer &&461461+ (event == SNDRV_TIMER_EVENT_START ||462462+ event == SNDRV_TIMER_EVENT_CONTINUE))463463+ resolution = snd_timer_hw_resolution(timer);473464 if (ti->ccallback)474465 ti->ccallback(ti, event, &tstamp, resolution);475466 if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)476467 return;477477- timer = ti->timer;478468 if (timer == NULL)479469 return;480470 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)···781771 spin_lock_irqsave(&timer->lock, flags);782772783773 /* remember the current resolution */784784- if (timer->hw.c_resolution)785785- resolution = timer->hw.c_resolution(timer);786786- else787787- resolution = timer->hw.resolution;774774+ resolution = snd_timer_hw_resolution(timer);788775789776 /* loop for all active instances790777 * Here we cannot use list_for_each_entry because the active_list of a···10211014 spin_lock_irqsave(&timer->lock, flags);10221015 if (event == SNDRV_TIMER_EVENT_MSTART ||10231016 event == SNDRV_TIMER_EVENT_MCONTINUE ||10241024- event == SNDRV_TIMER_EVENT_MRESUME) {10251025- if (timer->hw.c_resolution)10261026- resolution = timer->hw.c_resolution(timer);10271027- else10281028- resolution = timer->hw.resolution;10291029- }10171017+ event == SNDRV_TIMER_EVENT_MRESUME)10181018+ resolution = snd_timer_hw_resolution(timer);10301019 list_for_each_entry(ti, &timer->active_list_head, active_list) {10311020 if (ti->ccallback)10321021 ti->ccallback(ti, event, tstamp, resolution);···16591656 mutex_lock(®ister_mutex);16601657 t = snd_timer_find(&tid);16611658 if (t != NULL) {16621662- if (t->hw.c_resolution)16631663- gstatus.resolution = t->hw.c_resolution(t);16641664- else16651665- gstatus.resolution = t->hw.resolution;16591659+ spin_lock_irq(&t->lock);16601660+ gstatus.resolution = snd_timer_hw_resolution(t);16661661 if (t->hw.precise_resolution) {16671662 t->hw.precise_resolution(t, &gstatus.resolution_num,16681663 &gstatus.resolution_den);···16681667 gstatus.resolution_num = gstatus.resolution;16691668 gstatus.resolution_den = 1000000000uL;16701669 }16701670+ spin_unlock_irq(&t->lock);16711671 } else {16721672 err = -ENODEV;16731673 }
+9-7
sound/core/vmaster.c
···421421 kctl->private_free = master_free;422422423423 /* additional (constant) TLV read */424424- if (tlv &&425425- (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||426426- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||427427- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {428428- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;429429- memcpy(master->tlv, tlv, sizeof(master->tlv));430430- kctl->tlv.p = master->tlv;424424+ if (tlv) {425425+ unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE];426426+ if (type == SNDRV_CTL_TLVT_DB_SCALE ||427427+ type == SNDRV_CTL_TLVT_DB_MINMAX ||428428+ type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) {429429+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;430430+ memcpy(master->tlv, tlv, sizeof(master->tlv));431431+ kctl->tlv.p = master->tlv;432432+ }431433 }432434433435 return kctl;
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * dice-alesis.c - a part of driver for DICE based devices44+ *55+ * Copyright (c) 2018 Takashi Sakamoto66+ */77+88+#include "dice.h"99+1010+static const unsigned int1111+alesis_io14_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {1212+ {6, 6, 4}, /* Tx0 = Analog + S/PDIF. */1313+ {8, 4, 0}, /* Tx1 = ADAT1. */1414+};1515+1616+static const unsigned int1717+alesis_io26_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {1818+ {10, 10, 8}, /* Tx0 = Analog + S/PDIF. */1919+ {16, 8, 0}, /* Tx1 = ADAT1 + ADAT2. */2020+};2121+2222+int snd_dice_detect_alesis_formats(struct snd_dice *dice)2323+{2424+ __be32 reg;2525+ u32 data;2626+ int i;2727+ int err;2828+2929+ err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO, ®,3030+ sizeof(reg));3131+ if (err < 0)3232+ return err;3333+ data = be32_to_cpu(reg);3434+3535+ if (data == 4 || data == 6) {3636+ memcpy(dice->tx_pcm_chs, alesis_io14_tx_pcm_chs,3737+ MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *3838+ sizeof(unsigned int));3939+ } else {4040+ memcpy(dice->rx_pcm_chs, alesis_io26_tx_pcm_chs,4141+ MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *4242+ sizeof(unsigned int));4343+ }4444+4545+ for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)4646+ dice->rx_pcm_chs[0][i] = 8;4747+4848+ dice->tx_midi_ports[0] = 1;4949+ dice->rx_midi_ports[0] = 1;5050+5151+ return 0;5252+}
+172
sound/firewire/dice/dice-extension.c
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * dice-extension.c - a part of driver for DICE based devices44+ *55+ * Copyright (c) 2018 Takashi Sakamoto66+ */77+88+#include "dice.h"99+1010+/* For TCD2210/2220, TCAT defines extension of application protocol. */1111+1212+#define DICE_EXT_APP_SPACE 0xffffe0200000uLL1313+1414+#define DICE_EXT_APP_CAPS_OFFSET 0x001515+#define DICE_EXT_APP_CAPS_SIZE 0x041616+#define DICE_EXT_APP_CMD_OFFSET 0x081717+#define DICE_EXT_APP_CMD_SIZE 0x0c1818+#define DICE_EXT_APP_MIXER_OFFSET 0x101919+#define DICE_EXT_APP_MIXER_SIZE 0x142020+#define DICE_EXT_APP_PEAK_OFFSET 0x182121+#define DICE_EXT_APP_PEAK_SIZE 0x1c2222+#define DICE_EXT_APP_ROUTER_OFFSET 0x202323+#define DICE_EXT_APP_ROUTER_SIZE 0x242424+#define DICE_EXT_APP_STREAM_OFFSET 0x282525+#define DICE_EXT_APP_STREAM_SIZE 0x2c2626+#define DICE_EXT_APP_CURRENT_OFFSET 0x302727+#define DICE_EXT_APP_CURRENT_SIZE 0x342828+#define DICE_EXT_APP_STANDALONE_OFFSET 0x382929+#define DICE_EXT_APP_STANDALONE_SIZE 0x3c3030+#define DICE_EXT_APP_APPLICATION_OFFSET 0x403131+#define DICE_EXT_APP_APPLICATION_SIZE 0x443232+3333+#define EXT_APP_STREAM_TX_NUMBER 0x00003434+#define EXT_APP_STREAM_RX_NUMBER 0x00043535+#define EXT_APP_STREAM_ENTRIES 0x00083636+#define EXT_APP_STREAM_ENTRY_SIZE 0x010c3737+#define EXT_APP_NUMBER_AUDIO 0x00003838+#define EXT_APP_NUMBER_MIDI 0x00043939+#define EXT_APP_NAMES 0x00084040+#define EXT_APP_NAMES_SIZE 2564141+#define EXT_APP_AC3 0x01084242+4343+#define EXT_APP_CONFIG_LOW_ROUTER 0x00004444+#define EXT_APP_CONFIG_LOW_STREAM 0x10004545+#define EXT_APP_CONFIG_MIDDLE_ROUTER 0x20004646+#define EXT_APP_CONFIG_MIDDLE_STREAM 0x30004747+#define EXT_APP_CONFIG_HIGH_ROUTER 0x40004848+#define EXT_APP_CONFIG_HIGH_STREAM 0x50004949+5050+static inline int read_transaction(struct snd_dice *dice, u64 section_addr,5151+ u32 offset, void *buf, size_t len)5252+{5353+ return snd_fw_transaction(dice->unit,5454+ len == 4 ? TCODE_READ_QUADLET_REQUEST :5555+ TCODE_READ_BLOCK_REQUEST,5656+ section_addr + offset, buf, len, 0);5757+}5858+5959+static int read_stream_entries(struct snd_dice *dice, u64 section_addr,6060+ u32 base_offset, unsigned int stream_count,6161+ unsigned int mode,6262+ unsigned int pcm_channels[MAX_STREAMS][3],6363+ unsigned int midi_ports[MAX_STREAMS])6464+{6565+ u32 entry_offset;6666+ __be32 reg[2];6767+ int err;6868+ int i;6969+7070+ for (i = 0; i < stream_count; ++i) {7171+ entry_offset = base_offset + i * EXT_APP_STREAM_ENTRY_SIZE;7272+ err = read_transaction(dice, section_addr,7373+ entry_offset + EXT_APP_NUMBER_AUDIO,7474+ reg, sizeof(reg));7575+ if (err < 0)7676+ return err;7777+ pcm_channels[i][mode] = be32_to_cpu(reg[0]);7878+ midi_ports[i] = max(midi_ports[i], be32_to_cpu(reg[1]));7979+ }8080+8181+ return 0;8282+}8383+8484+static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)8585+{8686+ u32 base_offset;8787+ __be32 reg[2];8888+ unsigned int stream_count;8989+ int mode;9090+ int err = 0;9191+9292+ for (mode = 0; mode < SND_DICE_RATE_MODE_COUNT; ++mode) {9393+ unsigned int cap;9494+9595+ /*9696+ * Some models report stream formats at highest mode, however9797+ * they don't support the mode. Check clock capabilities.9898+ */9999+ if (mode == 2) {100100+ cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000;101101+ } else if (mode == 1) {102102+ cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000;103103+ } else {104104+ cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 |105105+ CLOCK_CAP_RATE_48000;106106+ }107107+ if (!(cap & dice->clock_caps))108108+ continue;109109+110110+ base_offset = 0x2000 * mode + 0x1000;111111+112112+ err = read_transaction(dice, section_addr,113113+ base_offset + EXT_APP_STREAM_TX_NUMBER,114114+ ®, sizeof(reg));115115+ if (err < 0)116116+ break;117117+118118+ base_offset += EXT_APP_STREAM_ENTRIES;119119+ stream_count = be32_to_cpu(reg[0]);120120+ err = read_stream_entries(dice, section_addr, base_offset,121121+ stream_count, mode,122122+ dice->tx_pcm_chs,123123+ dice->tx_midi_ports);124124+ if (err < 0)125125+ break;126126+127127+ base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;128128+ stream_count = be32_to_cpu(reg[1]);129129+ err = read_stream_entries(dice, section_addr, base_offset,130130+ stream_count,131131+ mode, dice->rx_pcm_chs,132132+ dice->rx_midi_ports);133133+ if (err < 0)134134+ break;135135+ }136136+137137+ return err;138138+}139139+140140+int snd_dice_detect_extension_formats(struct snd_dice *dice)141141+{142142+ __be32 *pointers;143143+ unsigned int i;144144+ u64 section_addr;145145+ int err;146146+147147+ pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL);148148+ if (pointers == NULL)149149+ return -ENOMEM;150150+151151+ err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,152152+ DICE_EXT_APP_SPACE, pointers,153153+ 9 * sizeof(__be32) * 2, 0);154154+ if (err < 0)155155+ goto end;156156+157157+ /* Check two of them for offset have the same value or not. */158158+ for (i = 0; i < 9; ++i) {159159+ int j;160160+161161+ for (j = i + 1; j < 9; ++j) {162162+ if (pointers[i * 2] == pointers[j * 2])163163+ goto end;164164+ }165165+ }166166+167167+ section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4;168168+ err = detect_stream_formats(dice, section_addr);169169+end:170170+ kfree(pointers);171171+ return err;172172+}
+7-2
sound/firewire/dice/dice-interface.h
···175175#define GLOBAL_SAMPLE_RATE 0x05c176176177177/*178178+ * Some old firmware versions do not have the following global registers.179179+ * Windows drivers produced by TCAT lost backward compatibility in its180180+ * early release because they can handle firmware only which supports the181181+ * following registers.182182+ */183183+184184+/*178185 * The version of the DICE driver specification that this device conforms to;179186 * read-only.180187 */181188#define GLOBAL_VERSION 0x060182182-183183-/* Some old firmware versions do not have the following global registers: */184189185190/*186191 * Supported sample rates and clock sources; read-only.
+7-16
sound/firewire/dice/dice-midi.c
···101101 .close = midi_close,102102 .trigger = midi_playback_trigger,103103 };104104- __be32 reg;105104 struct snd_rawmidi *rmidi;106105 struct snd_rawmidi_str *str;107106 unsigned int midi_in_ports, midi_out_ports;107107+ int i;108108 int err;109109110110- /*111111- * Use the number of MIDI conformant data channel at current sampling112112- * transfer frequency.113113- */114114- err = snd_dice_transaction_read_tx(dice, TX_NUMBER_MIDI,115115- ®, sizeof(reg));116116- if (err < 0)117117- return err;118118- midi_in_ports = be32_to_cpu(reg);119119-120120- err = snd_dice_transaction_read_rx(dice, RX_NUMBER_MIDI,121121- ®, sizeof(reg));122122- if (err < 0)123123- return err;124124- midi_out_ports = be32_to_cpu(reg);110110+ midi_in_ports = 0;111111+ midi_out_ports = 0;112112+ for (i = 0; i < MAX_STREAMS; ++i) {113113+ midi_in_ports = max(midi_in_ports, dice->tx_midi_ports[i]);114114+ midi_out_ports = max(midi_out_ports, dice->rx_midi_ports[i]);115115+ }125116126117 if (midi_in_ports + midi_out_ports == 0)127118 return 0;
+46
sound/firewire/dice/dice-mytek.c
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * dice-mytek.c - a part of driver for DICE based devices44+ *55+ * Copyright (c) 2018 Melvin Vermeeren66+ */77+88+#include "dice.h"99+1010+struct dice_mytek_spec {1111+ unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];1212+ unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];1313+};1414+1515+static const struct dice_mytek_spec stereo_192_dsd_dac = {1616+ /* AES, TOSLINK, SPDIF, ADAT inputs on device */1717+ .tx_pcm_chs = {{8, 8, 8}, {0, 0, 0} },1818+ /* PCM 44.1-192, native DSD64/DSD128 to device */1919+ .rx_pcm_chs = {{4, 4, 4}, {0, 0, 0} }2020+};2121+2222+/*2323+ * Mytek has a few other firewire-capable devices, though newer models appear2424+ * to lack the port more often than not. As I don't have access to any of them2525+ * they are missing here. An example is the Mytek 8x192 ADDA, which is DICE.2626+ */2727+2828+int snd_dice_detect_mytek_formats(struct snd_dice *dice)2929+{3030+ int i;3131+ const struct dice_mytek_spec *dev;3232+3333+ dev = &stereo_192_dsd_dac;3434+3535+ memcpy(dice->tx_pcm_chs, dev->tx_pcm_chs,3636+ MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));3737+ memcpy(dice->rx_pcm_chs, dev->rx_pcm_chs,3838+ MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));3939+4040+ for (i = 0; i < MAX_STREAMS; ++i) {4141+ dice->tx_midi_ports[i] = 0;4242+ dice->rx_midi_ports[i] = 0;4343+ }4444+4545+ return 0;4646+}
+161-70
sound/firewire/dice/dice-pcm.c
···991010#include "dice.h"11111212+static int dice_rate_constraint(struct snd_pcm_hw_params *params,1313+ struct snd_pcm_hw_rule *rule)1414+{1515+ struct snd_pcm_substream *substream = rule->private;1616+ struct snd_dice *dice = substream->private_data;1717+ unsigned int index = substream->pcm->device;1818+1919+ const struct snd_interval *c =2020+ hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);2121+ struct snd_interval *r =2222+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);2323+ struct snd_interval rates = {2424+ .min = UINT_MAX, .max = 0, .integer = 12525+ };2626+ unsigned int *pcm_channels;2727+ enum snd_dice_rate_mode mode;2828+ unsigned int i, rate;2929+3030+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)3131+ pcm_channels = dice->tx_pcm_chs[index];3232+ else3333+ pcm_channels = dice->rx_pcm_chs[index];3434+3535+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {3636+ rate = snd_dice_rates[i];3737+ if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)3838+ continue;3939+4040+ if (!snd_interval_test(c, pcm_channels[mode]))4141+ continue;4242+4343+ rates.min = min(rates.min, rate);4444+ rates.max = max(rates.max, rate);4545+ }4646+4747+ return snd_interval_refine(r, &rates);4848+}4949+5050+static int dice_channels_constraint(struct snd_pcm_hw_params *params,5151+ struct snd_pcm_hw_rule *rule)5252+{5353+ struct snd_pcm_substream *substream = rule->private;5454+ struct snd_dice *dice = substream->private_data;5555+ unsigned int index = substream->pcm->device;5656+5757+ const struct snd_interval *r =5858+ hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);5959+ struct snd_interval *c =6060+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);6161+ struct snd_interval channels = {6262+ .min = UINT_MAX, .max = 0, .integer = 16363+ };6464+ unsigned int *pcm_channels;6565+ enum snd_dice_rate_mode mode;6666+ unsigned int i, rate;6767+6868+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)6969+ pcm_channels = dice->tx_pcm_chs[index];7070+ else7171+ pcm_channels = dice->rx_pcm_chs[index];7272+7373+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {7474+ rate = snd_dice_rates[i];7575+ if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)7676+ continue;7777+7878+ if (!snd_interval_test(r, rate))7979+ continue;8080+8181+ channels.min = min(channels.min, pcm_channels[mode]);8282+ channels.max = max(channels.max, pcm_channels[mode]);8383+ }8484+8585+ return snd_interval_refine(c, &channels);8686+}8787+1288static int limit_channels_and_rates(struct snd_dice *dice,1389 struct snd_pcm_runtime *runtime,1490 enum amdtp_stream_direction dir,1515- unsigned int index, unsigned int size)9191+ unsigned int index)1692{1793 struct snd_pcm_hardware *hw = &runtime->hw;1818- struct amdtp_stream *stream;1919- unsigned int rate;2020- __be32 reg;2121- int err;9494+ unsigned int *pcm_channels;9595+ unsigned int i;22962323- /*2424- * Retrieve current Multi Bit Linear Audio data channel and limit to2525- * it.2626- */2727- if (dir == AMDTP_IN_STREAM) {2828- stream = &dice->tx_stream[index];2929- err = snd_dice_transaction_read_tx(dice,3030- size * index + TX_NUMBER_AUDIO,3131- ®, sizeof(reg));3232- } else {3333- stream = &dice->rx_stream[index];3434- err = snd_dice_transaction_read_rx(dice,3535- size * index + RX_NUMBER_AUDIO,3636- ®, sizeof(reg));9797+ if (dir == AMDTP_IN_STREAM)9898+ pcm_channels = dice->tx_pcm_chs[index];9999+ else100100+ pcm_channels = dice->rx_pcm_chs[index];101101+102102+ hw->channels_min = UINT_MAX;103103+ hw->channels_max = 0;104104+105105+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {106106+ enum snd_dice_rate_mode mode;107107+ unsigned int rate, channels;108108+109109+ rate = snd_dice_rates[i];110110+ if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)111111+ continue;112112+ hw->rates |= snd_pcm_rate_to_rate_bit(rate);113113+114114+ channels = pcm_channels[mode];115115+ if (channels == 0)116116+ continue;117117+ hw->channels_min = min(hw->channels_min, channels);118118+ hw->channels_max = max(hw->channels_max, channels);37119 }3838- if (err < 0)3939- return err;401204141- hw->channels_min = hw->channels_max = be32_to_cpu(reg);4242-4343- /* Retrieve current sampling transfer frequency and limit to it. */4444- err = snd_dice_transaction_get_rate(dice, &rate);4545- if (err < 0)4646- return err;4747-4848- hw->rates = snd_pcm_rate_to_rate_bit(rate);49121 snd_pcm_limit_hw_rates(runtime);5012251123 return 0;···12856{12957 struct snd_pcm_runtime *runtime = substream->runtime;13058 struct snd_pcm_hardware *hw = &runtime->hw;5959+ unsigned int index = substream->pcm->device;13160 enum amdtp_stream_direction dir;13261 struct amdtp_stream *stream;133133- __be32 reg[2];134134- unsigned int count, size;13562 int err;1366313764 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {13865 hw->formats = AM824_IN_PCM_FORMAT_BITS;13966 dir = AMDTP_IN_STREAM;140140- stream = &dice->tx_stream[substream->pcm->device];141141- err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg,142142- sizeof(reg));6767+ stream = &dice->tx_stream[index];14368 } else {14469 hw->formats = AM824_OUT_PCM_FORMAT_BITS;14570 dir = AMDTP_OUT_STREAM;146146- stream = &dice->rx_stream[substream->pcm->device];147147- err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg,148148- sizeof(reg));7171+ stream = &dice->rx_stream[index];14972 }150737474+ err = limit_channels_and_rates(dice, substream->runtime, dir,7575+ index);15176 if (err < 0)15277 return err;15378154154- count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);155155- if (substream->pcm->device >= count)156156- return -ENXIO;157157-158158- size = be32_to_cpu(reg[1]) * 4;159159- err = limit_channels_and_rates(dice, substream->runtime, dir,160160- substream->pcm->device, size);7979+ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,8080+ dice_rate_constraint, substream,8181+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);8282+ if (err < 0)8383+ return err;8484+ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,8585+ dice_channels_constraint, substream,8686+ SNDRV_PCM_HW_PARAM_RATE, -1);16187 if (err < 0)16288 return err;16389···16595static int pcm_open(struct snd_pcm_substream *substream)16696{16797 struct snd_dice *dice = substream->private_data;9898+ unsigned int source;9999+ bool internal;168100 int err;169101170102 err = snd_dice_stream_lock_try(dice);···176104 err = init_hw_info(dice, substream);177105 if (err < 0)178106 goto err_locked;107107+108108+ err = snd_dice_transaction_get_clock_source(dice, &source);109109+ if (err < 0)110110+ goto err_locked;111111+ switch (source) {112112+ case CLOCK_SOURCE_AES1:113113+ case CLOCK_SOURCE_AES2:114114+ case CLOCK_SOURCE_AES3:115115+ case CLOCK_SOURCE_AES4:116116+ case CLOCK_SOURCE_AES_ANY:117117+ case CLOCK_SOURCE_ADAT:118118+ case CLOCK_SOURCE_TDIF:119119+ case CLOCK_SOURCE_WC:120120+ internal = false;121121+ break;122122+ default:123123+ internal = true;124124+ break;125125+ }126126+127127+ /*128128+ * When source of clock is not internal or any PCM streams are running,129129+ * available sampling rate is limited at current sampling rate.130130+ */131131+ if (!internal ||132132+ amdtp_stream_pcm_running(&dice->tx_stream[0]) ||133133+ amdtp_stream_pcm_running(&dice->tx_stream[1]) ||134134+ amdtp_stream_pcm_running(&dice->rx_stream[0]) ||135135+ amdtp_stream_pcm_running(&dice->rx_stream[1])) {136136+ unsigned int rate;137137+138138+ err = snd_dice_transaction_get_rate(dice, &rate);139139+ if (err < 0)140140+ goto err_locked;141141+ substream->runtime->hw.rate_min = rate;142142+ substream->runtime->hw.rate_max = rate;143143+ }179144180145 snd_pcm_set_sync(substream);181146end:···427318 .page = snd_pcm_lib_get_vmalloc_page,428319 .mmap = snd_pcm_lib_mmap_vmalloc,429320 };430430- __be32 reg;431321 struct snd_pcm *pcm;432432- unsigned int i, max_capture, max_playback, capture, playback;322322+ unsigned int capture, playback;323323+ int i, j;433324 int err;434434-435435- /* Check whether PCM substreams are required. */436436- if (dice->force_two_pcms) {437437- max_capture = max_playback = 2;438438- } else {439439- max_capture = max_playback = 0;440440- err = snd_dice_transaction_read_tx(dice, TX_NUMBER, ®,441441- sizeof(reg));442442- if (err < 0)443443- return err;444444- max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);445445-446446- err = snd_dice_transaction_read_rx(dice, RX_NUMBER, ®,447447- sizeof(reg));448448- if (err < 0)449449- return err;450450- max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);451451- }452325453326 for (i = 0; i < MAX_STREAMS; i++) {454327 capture = playback = 0;455455- if (i < max_capture)456456- capture = 1;457457- if (i < max_playback)458458- playback = 1;459459- if (capture == 0 && playback == 0)460460- break;328328+ for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {329329+ if (dice->tx_pcm_chs[i][j] > 0)330330+ capture = 1;331331+ if (dice->rx_pcm_chs[i][j] > 0)332332+ playback = 1;333333+ }461334462335 err = snd_pcm_new(dice->card, "DICE", i, playback, capture,463336 &pcm);
+72-8
sound/firewire/dice/dice-proc.c
···148148 >> CLOCK_RATE_SHIFT));149149 snd_iprintf(buffer, " ext status: %08x\n", buf.global.extended_status);150150 snd_iprintf(buffer, " sample rate: %u\n", buf.global.sample_rate);151151- snd_iprintf(buffer, " version: %u.%u.%u.%u\n",152152- (buf.global.version >> 24) & 0xff,153153- (buf.global.version >> 16) & 0xff,154154- (buf.global.version >> 8) & 0xff,155155- (buf.global.version >> 0) & 0xff);156151 if (quadlets >= 90) {152152+ snd_iprintf(buffer, " version: %u.%u.%u.%u\n",153153+ (buf.global.version >> 24) & 0xff,154154+ (buf.global.version >> 16) & 0xff,155155+ (buf.global.version >> 8) & 0xff,156156+ (buf.global.version >> 0) & 0xff);157157 snd_iprintf(buffer, " clock caps:");158158 for (i = 0; i <= 6; ++i)159159 if (buf.global.clock_caps & (1 << i))···243243 }244244}245245246246-void snd_dice_create_proc(struct snd_dice *dice)246246+static void dice_proc_read_formation(struct snd_info_entry *entry,247247+ struct snd_info_buffer *buffer)248248+{249249+ static const char *const rate_labels[] = {250250+ [SND_DICE_RATE_MODE_LOW] = "low",251251+ [SND_DICE_RATE_MODE_MIDDLE] = "middle",252252+ [SND_DICE_RATE_MODE_HIGH] = "high",253253+ };254254+ struct snd_dice *dice = entry->private_data;255255+ int i, j;256256+257257+ snd_iprintf(buffer, "Output stream from unit:\n");258258+ for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)259259+ snd_iprintf(buffer, "\t%s", rate_labels[i]);260260+ snd_iprintf(buffer, "\tMIDI\n");261261+ for (i = 0; i < MAX_STREAMS; ++i) {262262+ snd_iprintf(buffer, "Tx %u:", i);263263+ for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)264264+ snd_iprintf(buffer, "\t%u", dice->tx_pcm_chs[i][j]);265265+ snd_iprintf(buffer, "\t%u\n", dice->tx_midi_ports[i]);266266+ }267267+268268+ snd_iprintf(buffer, "Input stream to unit:\n");269269+ for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)270270+ snd_iprintf(buffer, "\t%s", rate_labels[i]);271271+ snd_iprintf(buffer, "\n");272272+ for (i = 0; i < MAX_STREAMS; ++i) {273273+ snd_iprintf(buffer, "Rx %u:", i);274274+ for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)275275+ snd_iprintf(buffer, "\t%u", dice->rx_pcm_chs[i][j]);276276+ snd_iprintf(buffer, "\t%u\n", dice->rx_midi_ports[i]);277277+ }278278+}279279+280280+static void add_node(struct snd_dice *dice, struct snd_info_entry *root,281281+ const char *name,282282+ void (*op)(struct snd_info_entry *entry,283283+ struct snd_info_buffer *buffer))247284{248285 struct snd_info_entry *entry;249286250250- if (!snd_card_proc_new(dice->card, "dice", &entry))251251- snd_info_set_text_ops(entry, dice, dice_proc_read);287287+ entry = snd_info_create_card_entry(dice->card, name, root);288288+ if (!entry)289289+ return;290290+291291+ snd_info_set_text_ops(entry, dice, op);292292+ if (snd_info_register(entry) < 0)293293+ snd_info_free_entry(entry);294294+}295295+296296+void snd_dice_create_proc(struct snd_dice *dice)297297+{298298+ struct snd_info_entry *root;299299+300300+ /*301301+ * All nodes are automatically removed at snd_card_disconnect(),302302+ * by following to link list.303303+ */304304+ root = snd_info_create_card_entry(dice->card, "firewire",305305+ dice->card->proc_root);306306+ if (!root)307307+ return;308308+ root->mode = S_IFDIR | 0555;309309+ if (snd_info_register(root) < 0) {310310+ snd_info_free_entry(root);311311+ return;312312+ }313313+314314+ add_node(dice, root, "dice", dice_proc_read);315315+ add_node(dice, root, "formation", dice_proc_read_formation);252316}
+215-68
sound/firewire/dice/dice-stream.c
···3030 [6] = 192000,3131};32323333+int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,3434+ enum snd_dice_rate_mode *mode)3535+{3636+ /* Corresponding to each entry in snd_dice_rates. */3737+ static const enum snd_dice_rate_mode modes[] = {3838+ [0] = SND_DICE_RATE_MODE_LOW,3939+ [1] = SND_DICE_RATE_MODE_LOW,4040+ [2] = SND_DICE_RATE_MODE_LOW,4141+ [3] = SND_DICE_RATE_MODE_MIDDLE,4242+ [4] = SND_DICE_RATE_MODE_MIDDLE,4343+ [5] = SND_DICE_RATE_MODE_HIGH,4444+ [6] = SND_DICE_RATE_MODE_HIGH,4545+ };4646+ int i;4747+4848+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {4949+ if (!(dice->clock_caps & BIT(i)))5050+ continue;5151+ if (snd_dice_rates[i] != rate)5252+ continue;5353+5454+ *mode = modes[i];5555+ return 0;5656+ }5757+5858+ return -EINVAL;5959+}6060+3361/*3462 * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE3563 * to GLOBAL_STATUS. Especially, just after powering on, these are different.3664 */3737-static int ensure_phase_lock(struct snd_dice *dice)6565+static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)3866{3967 __be32 reg, nominal;6868+ u32 data;6969+ int i;4070 int err;41714272 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,···7444 if (err < 0)7545 return err;76464747+ data = be32_to_cpu(reg);4848+4949+ data &= ~CLOCK_RATE_MASK;5050+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {5151+ if (snd_dice_rates[i] == rate)5252+ break;5353+ }5454+ if (i == ARRAY_SIZE(snd_dice_rates))5555+ return -EINVAL;5656+ data |= i << CLOCK_RATE_SHIFT;5757+7758 if (completion_done(&dice->clock_accepted))7859 reinit_completion(&dice->clock_accepted);79606161+ reg = cpu_to_be32(data);8062 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,8163 ®, sizeof(reg));8264 if (err < 0)···234192 unsigned int rate, struct reg_params *params)235193{236194 __be32 reg[2];195195+ enum snd_dice_rate_mode mode;237196 unsigned int i, pcm_chs, midi_ports;238197 struct amdtp_stream *streams;239198 struct fw_iso_resources *resources;···249206 resources = dice->rx_resources;250207 }251208209209+ err = snd_dice_stream_get_rate_mode(dice, rate, &mode);210210+ if (err < 0)211211+ return err;212212+252213 for (i = 0; i < params->count; i++) {214214+ unsigned int pcm_cache;215215+ unsigned int midi_cache;216216+253217 if (dir == AMDTP_IN_STREAM) {218218+ pcm_cache = dice->tx_pcm_chs[i][mode];219219+ midi_cache = dice->tx_midi_ports[i];254220 err = snd_dice_transaction_read_tx(dice,255221 params->size * i + TX_NUMBER_AUDIO,256222 reg, sizeof(reg));257223 } else {224224+ pcm_cache = dice->rx_pcm_chs[i][mode];225225+ midi_cache = dice->rx_midi_ports[i];258226 err = snd_dice_transaction_read_rx(dice,259227 params->size * i + RX_NUMBER_AUDIO,260228 reg, sizeof(reg));···274220 return err;275221 pcm_chs = be32_to_cpu(reg[0]);276222 midi_ports = be32_to_cpu(reg[1]);223223+224224+ /* These are important for developer of this driver. */225225+ if (pcm_chs != pcm_cache || midi_ports != midi_cache) {226226+ dev_info(&dice->unit->device,227227+ "cache mismatch: pcm: %u:%u, midi: %u:%u\n",228228+ pcm_chs, pcm_cache, midi_ports, midi_cache);229229+ return -EPROTO;230230+ }277231278232 err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);279233 if (err < 0)···318256 return err;319257}320258259259+static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)260260+{261261+ struct reg_params tx_params, rx_params;262262+ int i;263263+ int err;264264+265265+ err = get_register_params(dice, &tx_params, &rx_params);266266+ if (err < 0)267267+ return err;268268+269269+ /* Stop transmission. */270270+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);271271+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);272272+ snd_dice_transaction_clear_enable(dice);273273+ release_resources(dice);274274+275275+ err = ensure_phase_lock(dice, rate);276276+ if (err < 0) {277277+ dev_err(&dice->unit->device, "fail to ensure phase lock\n");278278+ return err;279279+ }280280+281281+ /* Likely to have changed stream formats. */282282+ err = get_register_params(dice, &tx_params, &rx_params);283283+ if (err < 0)284284+ return err;285285+286286+ /* Start both streams. */287287+ err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);288288+ if (err < 0)289289+ goto error;290290+ err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);291291+ if (err < 0)292292+ goto error;293293+294294+ err = snd_dice_transaction_set_enable(dice);295295+ if (err < 0) {296296+ dev_err(&dice->unit->device, "fail to enable interface\n");297297+ goto error;298298+ }299299+300300+ for (i = 0; i < MAX_STREAMS; i++) {301301+ if ((i < tx_params.count &&302302+ !amdtp_stream_wait_callback(&dice->tx_stream[i],303303+ CALLBACK_TIMEOUT)) ||304304+ (i < rx_params.count &&305305+ !amdtp_stream_wait_callback(&dice->rx_stream[i],306306+ CALLBACK_TIMEOUT))) {307307+ err = -ETIMEDOUT;308308+ goto error;309309+ }310310+ }311311+312312+ return 0;313313+error:314314+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);315315+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);316316+ snd_dice_transaction_clear_enable(dice);317317+ release_resources(dice);318318+ return err;319319+}320320+321321/*322322 * MEMO: After this function, there're two states of streams:323323 * - None streams are running.···389265{390266 unsigned int curr_rate;391267 unsigned int i;392392- struct reg_params tx_params, rx_params;393393- bool need_to_start;268268+ enum snd_dice_rate_mode mode;394269 int err;395270396271 if (dice->substreams_counter == 0)397272 return -EIO;398273399399- err = get_register_params(dice, &tx_params, &rx_params);400400- if (err < 0)401401- return err;402402-274274+ /* Check sampling transmission frequency. */403275 err = snd_dice_transaction_get_rate(dice, &curr_rate);404276 if (err < 0) {405277 dev_err(&dice->unit->device,···405285 if (rate == 0)406286 rate = curr_rate;407287 if (rate != curr_rate)408408- return -EINVAL;288288+ goto restart;409289410410- /* Judge to need to restart streams. */411411- for (i = 0; i < MAX_STREAMS; i++) {412412- if (i < tx_params.count) {413413- if (amdtp_streaming_error(&dice->tx_stream[i]) ||414414- !amdtp_stream_running(&dice->tx_stream[i]))415415- break;416416- }417417- if (i < rx_params.count) {418418- if (amdtp_streaming_error(&dice->rx_stream[i]) ||419419- !amdtp_stream_running(&dice->rx_stream[i]))420420- break;421421- }290290+ /* Check error of packet streaming. */291291+ for (i = 0; i < MAX_STREAMS; ++i) {292292+ if (amdtp_streaming_error(&dice->tx_stream[i]))293293+ break;294294+ if (amdtp_streaming_error(&dice->rx_stream[i]))295295+ break;422296 }423423- need_to_start = (i < MAX_STREAMS);297297+ if (i < MAX_STREAMS)298298+ goto restart;424299425425- if (need_to_start) {426426- /* Stop transmission. */427427- snd_dice_transaction_clear_enable(dice);428428- stop_streams(dice, AMDTP_IN_STREAM, &tx_params);429429- stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);430430- release_resources(dice);431431-432432- err = ensure_phase_lock(dice);433433- if (err < 0) {434434- dev_err(&dice->unit->device,435435- "fail to ensure phase lock\n");436436- return err;437437- }438438-439439- /* Start both streams. */440440- err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);441441- if (err < 0)442442- goto error;443443- err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);444444- if (err < 0)445445- goto error;446446-447447- err = snd_dice_transaction_set_enable(dice);448448- if (err < 0) {449449- dev_err(&dice->unit->device,450450- "fail to enable interface\n");451451- goto error;452452- }453453-454454- for (i = 0; i < MAX_STREAMS; i++) {455455- if ((i < tx_params.count &&456456- !amdtp_stream_wait_callback(&dice->tx_stream[i],457457- CALLBACK_TIMEOUT)) ||458458- (i < rx_params.count &&459459- !amdtp_stream_wait_callback(&dice->rx_stream[i],460460- CALLBACK_TIMEOUT))) {461461- err = -ETIMEDOUT;462462- goto error;463463- }464464- }300300+ /* Check required streams are running or not. */301301+ err = snd_dice_stream_get_rate_mode(dice, rate, &mode);302302+ if (err < 0)303303+ return err;304304+ for (i = 0; i < MAX_STREAMS; ++i) {305305+ if (dice->tx_pcm_chs[i][mode] > 0 &&306306+ !amdtp_stream_running(&dice->tx_stream[i]))307307+ break;308308+ if (dice->rx_pcm_chs[i][mode] > 0 &&309309+ !amdtp_stream_running(&dice->rx_stream[i]))310310+ break;465311 }312312+ if (i < MAX_STREAMS)313313+ goto restart;466314467467- return err;468468-error:469469- snd_dice_transaction_clear_enable(dice);470470- stop_streams(dice, AMDTP_IN_STREAM, &tx_params);471471- stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);472472- release_resources(dice);473473- return err;315315+ return 0;316316+restart:317317+ return start_duplex_streams(dice, rate);474318}475319476320/*···566482 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);567483 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);568484 }485485+}486486+487487+int snd_dice_stream_detect_current_formats(struct snd_dice *dice)488488+{489489+ unsigned int rate;490490+ enum snd_dice_rate_mode mode;491491+ __be32 reg[2];492492+ struct reg_params tx_params, rx_params;493493+ int i;494494+ int err;495495+496496+ /* If extended protocol is available, detect detail spec. */497497+ err = snd_dice_detect_extension_formats(dice);498498+ if (err >= 0)499499+ return err;500500+501501+ /*502502+ * Available stream format is restricted at current mode of sampling503503+ * clock.504504+ */505505+ err = snd_dice_transaction_get_rate(dice, &rate);506506+ if (err < 0)507507+ return err;508508+509509+ err = snd_dice_stream_get_rate_mode(dice, rate, &mode);510510+ if (err < 0)511511+ return err;512512+513513+ /*514514+ * Just after owning the unit (GLOBAL_OWNER), the unit can return515515+ * invalid stream formats. Selecting clock parameters have an effect516516+ * for the unit to refine it.517517+ */518518+ err = ensure_phase_lock(dice, rate);519519+ if (err < 0)520520+ return err;521521+522522+ err = get_register_params(dice, &tx_params, &rx_params);523523+ if (err < 0)524524+ return err;525525+526526+ for (i = 0; i < tx_params.count; ++i) {527527+ err = snd_dice_transaction_read_tx(dice,528528+ tx_params.size * i + TX_NUMBER_AUDIO,529529+ reg, sizeof(reg));530530+ if (err < 0)531531+ return err;532532+ dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);533533+ dice->tx_midi_ports[i] = max_t(unsigned int,534534+ be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);535535+ }536536+ for (i = 0; i < rx_params.count; ++i) {537537+ err = snd_dice_transaction_read_rx(dice,538538+ rx_params.size * i + RX_NUMBER_AUDIO,539539+ reg, sizeof(reg));540540+ if (err < 0)541541+ return err;542542+ dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);543543+ dice->rx_midi_ports[i] = max_t(unsigned int,544544+ be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);545545+ }546546+547547+ return 0;569548}570549571550static void dice_lock_changed(struct snd_dice *dice)
···6565{6666 struct hdac_device *codec = dev_to_hdac_dev(dev);6767 unsigned int verb = get_verb(reg);6868+ const unsigned int *v;6869 int i;69707070- for (i = 0; i < codec->vendor_verbs.used; i++) {7171- unsigned int *v = snd_array_elem(&codec->vendor_verbs, i);7171+ snd_array_for_each(&codec->vendor_verbs, i, v) {7272 if (verb == *v)7373 return true;7474 }
+2-2
sound/isa/cmi8328.c
···192192}193193194194/* find index of an item in "-1"-ended array */195195-int array_find(int array[], int item)195195+static int array_find(int array[], int item)196196{197197 int i;198198···203203 return -1;204204}205205/* the same for long */206206-int array_find_l(long array[], long item)206206+static int array_find_l(long array[], long item)207207{208208 int i;209209
···258258259259 while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY) 260260 && --retry)261261- mdelay(1);261261+ usleep_range(1000, 2000);262262 if (!retry) {263263 dev_err(chip->card->dev, "[%s] Link is not ready.\n",264264 __func__);···872872 ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */873873 ad1889_readw(chip, AD_DS_CCS); /* flush posted write */874874875875- mdelay(10);875875+ usleep_range(10000, 11000);876876877877 /* enable Master and Target abort interrupts */878878 ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
+6-6
sound/pci/asihpi/asihpi.c
···6969static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;7070static bool enable_hpi_hwdep = 1;71717272-module_param_array(index, int, NULL, S_IRUGO);7272+module_param_array(index, int, NULL, 0444);7373MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");74747575-module_param_array(id, charp, NULL, S_IRUGO);7575+module_param_array(id, charp, NULL, 0444);7676MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");77777878-module_param_array(enable, bool, NULL, S_IRUGO);7878+module_param_array(enable, bool, NULL, 0444);7979MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard.");80808181-module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR);8181+module_param(enable_hpi_hwdep, bool, 0644);8282MODULE_PARM_DESC(enable_hpi_hwdep,8383 "ALSA enable HPI hwdep for AudioScience soundcard ");84848585/* identify driver */8686#ifdef KERNEL_ALSA_BUILD8787static char *build_info = "Built using headers from kernel source";8888-module_param(build_info, charp, S_IRUGO);8888+module_param(build_info, charp, 0444);8989MODULE_PARM_DESC(build_info, "Built using headers from kernel source");9090#else9191static char *build_info = "Built within ALSA source";9292-module_param(build_info, charp, S_IRUGO);9292+module_param(build_info, charp, 0444);9393MODULE_PARM_DESC(build_info, "Built within ALSA source");9494#endif9595
+2-2
sound/pci/asihpi/hpioctl.c
···4646#endif47474848static int prealloc_stream_buf;4949-module_param(prealloc_stream_buf, int, S_IRUGO);4949+module_param(prealloc_stream_buf, int, 0444);5050MODULE_PARM_DESC(prealloc_stream_buf,5151 "Preallocate size for per-adapter stream buffer");52525353/* Allow the debug level to be changed after module load.5454 E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel5555*/5656-module_param(hpi_debug_level, int, S_IRUGO | S_IWUSR);5656+module_param(hpi_debug_level, int, 0644);5757MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5");58585959/* List of adapters found */
···11391139 struct snd_ctl_elem_value *val;11401140 unsigned int i;1141114111421142- val = kmalloc(sizeof(*val), GFP_ATOMIC);11421142+ val = kmalloc(sizeof(*val), GFP_KERNEL);11431143 if (!val)11441144 return -ENOMEM;11451145 for (i = 0; i < CM_SAVED_MIXERS; i++) {
···248248static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr)249249{250250 if (addr & ~emu->dma_mask) {251251- dev_err(emu->card->dev,251251+ dev_err_ratelimited(emu->card->dev,252252 "max memory size is 0x%lx (addr = 0x%lx)!!\n",253253 emu->dma_mask, (unsigned long)addr);254254 return 0;255255 }256256 if (addr & (EMUPAGESIZE-1)) {257257- dev_err(emu->card->dev, "page is not aligned\n");257257+ dev_err_ratelimited(emu->card->dev, "page is not aligned\n");258258 return 0;259259 }260260 return 1;···345345 else346346 addr = snd_pcm_sgbuf_get_addr(substream, ofs);347347 if (! is_valid_page(emu, addr)) {348348- dev_err(emu->card->dev,348348+ dev_err_ratelimited(emu->card->dev,349349 "emu: failure page = %d\n", idx);350350 mutex_unlock(&hdr->block_mutex);351351 return NULL;
+4
sound/pci/hda/Kconfig
···127127128128config SND_HDA_CODEC_HDMI129129 tristate "Build HDMI/DisplayPort HD-audio codec support"130130+ select SND_DYNAMIC_MINORS130131 help131132 Say Y or M here to include HDMI and DisplayPort HD-audio codec132133 support in snd-hda-intel driver. This includes all AMD/ATI,133134 Intel and Nvidia HDMI/DisplayPort codecs.135135+136136+ Note that this option mandatorily enables CONFIG_SND_DYNAMIC_MINORS137137+ to assure the multiple streams for DP-MST support.134138135139comment "Set to Y if you want auto-loading the codec driver"136140 depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m
+5-5
sound/pci/hda/hda_auto_parser.c
···793793 */794794void snd_hda_apply_verbs(struct hda_codec *codec)795795{796796+ const struct hda_verb **v;796797 int i;797797- for (i = 0; i < codec->verbs.used; i++) {798798- struct hda_verb **v = snd_array_elem(&codec->verbs, i);798798+799799+ snd_array_for_each(&codec->verbs, i, v)799800 snd_hda_sequence_write(codec, *v);800800- }801801}802802EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);803803···890890static bool pin_config_match(struct hda_codec *codec,891891 const struct hda_pintbl *pins)892892{893893+ const struct hda_pincfg *pin;893894 int i;894895895895- for (i = 0; i < codec->init_pins.used; i++) {896896- struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);896896+ snd_array_for_each(&codec->init_pins, i, pin) {897897 hda_nid_t nid = pin->nid;898898 u32 cfg = pin->cfg;899899 const struct hda_pintbl *t_pins;
+41-29
sound/pci/hda/hda_codec.c
···481481 struct snd_array *array,482482 hda_nid_t nid)483483{484484+ struct hda_pincfg *pin;484485 int i;485485- for (i = 0; i < array->used; i++) {486486- struct hda_pincfg *pin = snd_array_elem(array, i);486486+487487+ snd_array_for_each(array, i, pin) {487488 if (pin->nid == nid)488489 return pin;489490 }···619618 */620619void snd_hda_shutup_pins(struct hda_codec *codec)621620{621621+ const struct hda_pincfg *pin;622622 int i;623623+623624 /* don't shut up pins when unloading the driver; otherwise it breaks624625 * the default pin setup at the next load of the driver625626 */626627 if (codec->bus->shutdown)627628 return;628628- for (i = 0; i < codec->init_pins.used; i++) {629629- struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);629629+ snd_array_for_each(&codec->init_pins, i, pin) {630630 /* use read here for syncing after issuing each verb */631631 snd_hda_codec_read(codec, pin->nid, 0,632632 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);···640638/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */641639static void restore_shutup_pins(struct hda_codec *codec)642640{641641+ const struct hda_pincfg *pin;643642 int i;643643+644644 if (!codec->pins_shutup)645645 return;646646 if (codec->bus->shutdown)647647 return;648648- for (i = 0; i < codec->init_pins.used; i++) {649649- struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);648648+ snd_array_for_each(&codec->init_pins, i, pin) {650649 snd_hda_codec_write(codec, pin->nid, 0,651650 AC_VERB_SET_PIN_WIDGET_CONTROL,652651 pin->ctrl);···700697 struct hda_cvt_setup *p;701698 int i;702699703703- for (i = 0; i < codec->cvt_setups.used; i++) {704704- p = snd_array_elem(&codec->cvt_setups, i);700700+ snd_array_for_each(&codec->cvt_setups, i, p) {705701 if (p->nid == nid)706702 return p;707703 }···10781076 /* make other inactive cvts with the same stream-tag dirty */10791077 type = get_wcaps_type(get_wcaps(codec, nid));10801078 list_for_each_codec(c, codec->bus) {10811081- for (i = 0; i < c->cvt_setups.used; i++) {10821082- p = snd_array_elem(&c->cvt_setups, i);10791079+ snd_array_for_each(&c->cvt_setups, i, p) {10831080 if (!p->active && p->stream_tag == stream_tag &&10841081 get_wcaps_type(get_wcaps(c, p->nid)) == type)10851082 p->dirty = 1;···11411140static void purify_inactive_streams(struct hda_codec *codec)11421141{11431142 struct hda_codec *c;11431143+ struct hda_cvt_setup *p;11441144 int i;1145114511461146 list_for_each_codec(c, codec->bus) {11471147- for (i = 0; i < c->cvt_setups.used; i++) {11481148- struct hda_cvt_setup *p;11491149- p = snd_array_elem(&c->cvt_setups, i);11471147+ snd_array_for_each(&c->cvt_setups, i, p) {11501148 if (p->dirty)11511149 really_cleanup_stream(c, p);11521150 }···11561156/* clean up all streams; called from suspend */11571157static void hda_cleanup_all_streams(struct hda_codec *codec)11581158{11591159+ struct hda_cvt_setup *p;11591160 int i;1160116111611161- for (i = 0; i < codec->cvt_setups.used; i++) {11621162- struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);11621162+ snd_array_for_each(&codec->cvt_setups, i, p) {11631163 if (p->stream_tag)11641164 really_cleanup_stream(codec, p);11651165 }···14931493 val1 = ((int)val1) * ((int)val2);14941494 if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))14951495 val2 |= TLV_DB_SCALE_MUTE;14961496- tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;14971497- tlv[1] = 2 * sizeof(unsigned int);14981498- tlv[2] = val1;14991499- tlv[3] = val2;14961496+ tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;14971497+ tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);14981498+ tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = val1;14991499+ tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = val2;15001500}1501150115021502/**···15441544 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;15451545 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;15461546 step = (step + 1) * 25;15471547- tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;15481548- tlv[1] = 2 * sizeof(unsigned int);15491549- tlv[2] = -nums * step;15501550- tlv[3] = step;15471547+ tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;15481548+ tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);15491549+ tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = -nums * step;15501550+ tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = step;15511551}15521552EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);15531553···18451845 } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)18461846 tlv = kctl->tlv.p;1847184718481848- if (!tlv || tlv[0] != SNDRV_CTL_TLVT_DB_SCALE)18481848+ if (!tlv || tlv[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)18491849 return 0;1850185018511851- step = tlv[3];18511851+ step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP];18521852 step &= ~TLV_DB_SCALE_MUTE;18531853 if (!step)18541854 return 0;···18601860 }1861186118621862 arg->step = step;18631863- val = -tlv[2] / step;18631863+ val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step;18641864 if (val > 0) {18651865 put_kctl_with_value(slave, val);18661866 return val;···21752175 int idx = kcontrol->private_value;21762176 struct hda_spdif_out *spdif;2177217721782178+ if (WARN_ON(codec->spdif_out.used <= idx))21792179+ return -EINVAL;21782180 mutex_lock(&codec->spdif_mutex);21792181 spdif = snd_array_elem(&codec->spdif_out, idx);21802182 ucontrol->value.iec958.status[0] = spdif->status & 0xff;···22842282 unsigned short val;22852283 int change;2286228422852285+ if (WARN_ON(codec->spdif_out.used <= idx))22862286+ return -EINVAL;22872287 mutex_lock(&codec->spdif_mutex);22882288 spdif = snd_array_elem(&codec->spdif_out, idx);22892289 nid = spdif->nid;···23122308 int idx = kcontrol->private_value;23132309 struct hda_spdif_out *spdif;2314231023112311+ if (WARN_ON(codec->spdif_out.used <= idx))23122312+ return -EINVAL;23152313 mutex_lock(&codec->spdif_mutex);23162314 spdif = snd_array_elem(&codec->spdif_out, idx);23172315 ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;···23422336 unsigned short val;23432337 int change;2344233823392339+ if (WARN_ON(codec->spdif_out.used <= idx))23402340+ return -EINVAL;23452341 mutex_lock(&codec->spdif_mutex);23462342 spdif = snd_array_elem(&codec->spdif_out, idx);23472343 nid = spdif->nid;···24692461struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,24702462 hda_nid_t nid)24712463{24642464+ struct hda_spdif_out *spdif;24722465 int i;24732473- for (i = 0; i < codec->spdif_out.used; i++) {24742474- struct hda_spdif_out *spdif =24752475- snd_array_elem(&codec->spdif_out, i);24662466+24672467+ snd_array_for_each(&codec->spdif_out, i, spdif) {24762468 if (spdif->nid == nid)24772469 return spdif;24782470 }···24912483{24922484 struct hda_spdif_out *spdif;2493248524862486+ if (WARN_ON(codec->spdif_out.used <= idx))24872487+ return;24942488 mutex_lock(&codec->spdif_mutex);24952489 spdif = snd_array_elem(&codec->spdif_out, idx);24962490 spdif->nid = (u16)-1;···25132503 struct hda_spdif_out *spdif;25142504 unsigned short val;2515250525062506+ if (WARN_ON(codec->spdif_out.used <= idx))25072507+ return;25162508 mutex_lock(&codec->spdif_mutex);25172509 spdif = snd_array_elem(&codec->spdif_out, idx);25182510 if (spdif->nid != nid) {
···8686static bool autoclock = true;8787static char *quirk_alias[SNDRV_CARDS];88888989+bool snd_usb_use_vmalloc = true;9090+8991module_param_array(index, int, NULL, 0444);9092MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");9193module_param_array(id, charp, NULL, 0444);···107105MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");108106module_param_array(quirk_alias, charp, NULL, 0444);109107MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");108108+module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);109109+MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");110110111111/*112112 * we keep the snd_usb_audio_t instances by ourselves for merging···225221 struct usb_device *dev = chip->dev;226222 struct usb_host_interface *host_iface;227223 struct usb_interface_descriptor *altsd;228228- void *control_header;229224 int i, protocol;230230- int rest_bytes;231225232226 /* find audiocontrol interface */233227 host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];234234- control_header = snd_usb_find_csint_desc(host_iface->extra,235235- host_iface->extralen,236236- NULL, UAC_HEADER);237228 altsd = get_iface_desc(host_iface);238229 protocol = altsd->bInterfaceProtocol;239239-240240- if (!control_header) {241241- dev_err(&dev->dev, "cannot find UAC_HEADER\n");242242- return -EINVAL;243243- }244244-245245- rest_bytes = (void *)(host_iface->extra + host_iface->extralen) -246246- control_header;247247-248248- /* just to be sure -- this shouldn't hit at all */249249- if (rest_bytes <= 0) {250250- dev_err(&dev->dev, "invalid control header\n");251251- return -EINVAL;252252- }253230254231 switch (protocol) {255232 default:···240255 /* fall through */241256242257 case UAC_VERSION_1: {243243- struct uac1_ac_header_descriptor *h1 = control_header;258258+ struct uac1_ac_header_descriptor *h1;259259+ int rest_bytes;260260+261261+ h1 = snd_usb_find_csint_desc(host_iface->extra,262262+ host_iface->extralen,263263+ NULL, UAC_HEADER);264264+ if (!h1) {265265+ dev_err(&dev->dev, "cannot find UAC_HEADER\n");266266+ return -EINVAL;267267+ }268268+269269+ rest_bytes = (void *)(host_iface->extra +270270+ host_iface->extralen) - (void *)h1;271271+272272+ /* just to be sure -- this shouldn't hit at all */273273+ if (rest_bytes <= 0) {274274+ dev_err(&dev->dev, "invalid control header\n");275275+ return -EINVAL;276276+ }244277245278 if (rest_bytes < sizeof(*h1)) {246279 dev_err(&dev->dev, "too short v1 buffer descriptor\n");···311308 return -EINVAL;312309 }313310311311+ if (protocol == UAC_VERSION_3) {312312+ int badd = assoc->bFunctionSubClass;313313+314314+ if (badd != UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 &&315315+ (badd < UAC3_FUNCTION_SUBCLASS_GENERIC_IO ||316316+ badd > UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE)) {317317+ dev_err(&dev->dev,318318+ "Unsupported UAC3 BADD profile\n");319319+ return -EINVAL;320320+ }321321+322322+ chip->badd_profile = badd;323323+ }324324+314325 for (i = 0; i < assoc->bInterfaceCount; i++) {315326 int intf = assoc->bFirstInterface + i;316327···346329 *347330 */348331349349-static int snd_usb_audio_free(struct snd_usb_audio *chip)332332+static void snd_usb_audio_free(struct snd_card *card)350333{334334+ struct snd_usb_audio *chip = card->private_data;351335 struct snd_usb_endpoint *ep, *n;352336353337 list_for_each_entry_safe(ep, n, &chip->ep_list, list)···357339 mutex_destroy(&chip->mutex);358340 if (!atomic_read(&chip->shutdown))359341 dev_set_drvdata(&chip->dev->dev, NULL);360360- kfree(chip);361361- return 0;362342}363343364364-static int snd_usb_audio_dev_free(struct snd_device *device)344344+static void usb_audio_make_shortname(struct usb_device *dev,345345+ struct snd_usb_audio *chip,346346+ const struct snd_usb_audio_quirk *quirk)365347{366366- struct snd_usb_audio *chip = device->device_data;367367- return snd_usb_audio_free(chip);368368-}348348+ struct snd_card *card = chip->card;369349370370-/*371371- * create a chip instance and set its names.372372- */373373-static int snd_usb_audio_create(struct usb_interface *intf,374374- struct usb_device *dev, int idx,375375- const struct snd_usb_audio_quirk *quirk,376376- unsigned int usb_id,377377- struct snd_usb_audio **rchip)378378-{379379- struct snd_card *card;380380- struct snd_usb_audio *chip;381381- int err, len;382382- char component[14];383383- static struct snd_device_ops ops = {384384- .dev_free = snd_usb_audio_dev_free,385385- };386386-387387- *rchip = NULL;388388-389389- switch (snd_usb_get_speed(dev)) {390390- case USB_SPEED_LOW:391391- case USB_SPEED_FULL:392392- case USB_SPEED_HIGH:393393- case USB_SPEED_WIRELESS:394394- case USB_SPEED_SUPER:395395- case USB_SPEED_SUPER_PLUS:396396- break;397397- default:398398- dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev));399399- return -ENXIO;350350+ if (quirk && quirk->product_name && *quirk->product_name) {351351+ strlcpy(card->shortname, quirk->product_name,352352+ sizeof(card->shortname));353353+ return;400354 }401401-402402- err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,403403- 0, &card);404404- if (err < 0) {405405- dev_err(&dev->dev, "cannot create card instance %d\n", idx);406406- return err;407407- }408408-409409- chip = kzalloc(sizeof(*chip), GFP_KERNEL);410410- if (! chip) {411411- snd_card_free(card);412412- return -ENOMEM;413413- }414414-415415- mutex_init(&chip->mutex);416416- init_waitqueue_head(&chip->shutdown_wait);417417- chip->index = idx;418418- chip->dev = dev;419419- chip->card = card;420420- chip->setup = device_setup[idx];421421- chip->autoclock = autoclock;422422- atomic_set(&chip->active, 1); /* avoid autopm during probing */423423- atomic_set(&chip->usage_count, 0);424424- atomic_set(&chip->shutdown, 0);425425-426426- chip->usb_id = usb_id;427427- INIT_LIST_HEAD(&chip->pcm_list);428428- INIT_LIST_HEAD(&chip->ep_list);429429- INIT_LIST_HEAD(&chip->midi_list);430430- INIT_LIST_HEAD(&chip->mixer_list);431431-432432- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {433433- snd_usb_audio_free(chip);434434- snd_card_free(card);435435- return err;436436- }437437-438438- strcpy(card->driver, "USB-Audio");439439- sprintf(component, "USB%04x:%04x",440440- USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));441441- snd_component_add(card, component);442355443356 /* retrieve the device string as shortname */444444- if (quirk && quirk->product_name && *quirk->product_name) {445445- strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname));446446- } else {447447- if (!dev->descriptor.iProduct ||448448- usb_string(dev, dev->descriptor.iProduct,449449- card->shortname, sizeof(card->shortname)) <= 0) {450450- /* no name available from anywhere, so use ID */451451- sprintf(card->shortname, "USB Device %#04x:%#04x",452452- USB_ID_VENDOR(chip->usb_id),453453- USB_ID_PRODUCT(chip->usb_id));454454- }357357+ if (!dev->descriptor.iProduct ||358358+ usb_string(dev, dev->descriptor.iProduct,359359+ card->shortname, sizeof(card->shortname)) <= 0) {360360+ /* no name available from anywhere, so use ID */361361+ sprintf(card->shortname, "USB Device %#04x:%#04x",362362+ USB_ID_VENDOR(chip->usb_id),363363+ USB_ID_PRODUCT(chip->usb_id));455364 }456456- strim(card->shortname);457365458458- /* retrieve the vendor and device strings as longname */366366+ strim(card->shortname);367367+}368368+369369+static void usb_audio_make_longname(struct usb_device *dev,370370+ struct snd_usb_audio *chip,371371+ const struct snd_usb_audio_quirk *quirk)372372+{373373+ struct snd_card *card = chip->card;374374+ int len;375375+376376+ /* shortcut - if any pre-defined string is given, use it */377377+ if (quirk && quirk->profile_name && *quirk->profile_name) {378378+ strlcpy(card->longname, quirk->profile_name,379379+ sizeof(card->longname));380380+ return;381381+ }382382+459383 if (quirk && quirk->vendor_name && *quirk->vendor_name) {460384 len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));461385 } else {386386+ /* retrieve the vendor and device strings as longname */462387 if (dev->descriptor.iManufacturer)463388 len = usb_string(dev, dev->descriptor.iManufacturer,464389 card->longname, sizeof(card->longname));···441480 default:442481 break;443482 }483483+}484484+485485+/*486486+ * create a chip instance and set its names.487487+ */488488+static int snd_usb_audio_create(struct usb_interface *intf,489489+ struct usb_device *dev, int idx,490490+ const struct snd_usb_audio_quirk *quirk,491491+ unsigned int usb_id,492492+ struct snd_usb_audio **rchip)493493+{494494+ struct snd_card *card;495495+ struct snd_usb_audio *chip;496496+ int err;497497+ char component[14];498498+499499+ *rchip = NULL;500500+501501+ switch (snd_usb_get_speed(dev)) {502502+ case USB_SPEED_LOW:503503+ case USB_SPEED_FULL:504504+ case USB_SPEED_HIGH:505505+ case USB_SPEED_WIRELESS:506506+ case USB_SPEED_SUPER:507507+ case USB_SPEED_SUPER_PLUS:508508+ break;509509+ default:510510+ dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev));511511+ return -ENXIO;512512+ }513513+514514+ err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,515515+ sizeof(*chip), &card);516516+ if (err < 0) {517517+ dev_err(&dev->dev, "cannot create card instance %d\n", idx);518518+ return err;519519+ }520520+521521+ chip = card->private_data;522522+ mutex_init(&chip->mutex);523523+ init_waitqueue_head(&chip->shutdown_wait);524524+ chip->index = idx;525525+ chip->dev = dev;526526+ chip->card = card;527527+ chip->setup = device_setup[idx];528528+ chip->autoclock = autoclock;529529+ atomic_set(&chip->active, 1); /* avoid autopm during probing */530530+ atomic_set(&chip->usage_count, 0);531531+ atomic_set(&chip->shutdown, 0);532532+533533+ chip->usb_id = usb_id;534534+ INIT_LIST_HEAD(&chip->pcm_list);535535+ INIT_LIST_HEAD(&chip->ep_list);536536+ INIT_LIST_HEAD(&chip->midi_list);537537+ INIT_LIST_HEAD(&chip->mixer_list);538538+539539+ card->private_free = snd_usb_audio_free;540540+541541+ strcpy(card->driver, "USB-Audio");542542+ sprintf(component, "USB%04x:%04x",543543+ USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));544544+ snd_component_add(card, component);545545+546546+ usb_audio_make_shortname(dev, chip, quirk);547547+ usb_audio_make_longname(dev, chip, quirk);444548445549 snd_usb_audio_create_proc(chip);446550
+18-9
sound/usb/clock.c
···443443 data[0] = rate;444444 data[1] = rate >> 8;445445 data[2] = rate >> 16;446446- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,447447- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,448448- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,449449- data, sizeof(data))) < 0) {446446+ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,447447+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,448448+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,449449+ data, sizeof(data));450450+ if (err < 0) {450451 dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",451452 iface, fmt->altsetting, rate, ep);452453 return err;···461460 if (chip->sample_rate_read_error > 2)462461 return 0;463462464464- if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,465465- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,466466- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,467467- data, sizeof(data))) < 0) {463463+ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,464464+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,465465+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,466466+ data, sizeof(data));467467+ if (err < 0) {468468 dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",469469 iface, fmt->altsetting, ep);470470 chip->sample_rate_read_error++;···589587 default:590588 return set_sample_rate_v1(chip, iface, alts, fmt, rate);591589592592- case UAC_VERSION_2:593590 case UAC_VERSION_3:591591+ if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {592592+ if (rate != UAC3_BADD_SAMPLING_RATE)593593+ return -ENXIO;594594+ else595595+ return 0;596596+ }597597+ /* fall through */598598+ case UAC_VERSION_2:594599 return set_sample_rate_v2v3(chip, iface, alts, fmt, rate);595600 }596601}
-4
sound/usb/helper.h
···1818 * retrieve usb_interface descriptor from the host interface1919 * (conditional for compatibility with the older API)2020 */2121-#ifndef get_iface_desc2221#define get_iface_desc(iface) (&(iface)->desc)2322#define get_endpoint(alt,ep) (&(alt)->endpoint[ep].desc)2423#define get_ep_desc(ep) (&(ep)->desc)2524#define get_cfg_desc(cfg) (&(cfg)->desc)2626-#endif27252828-#ifndef snd_usb_get_speed2926#define snd_usb_get_speed(dev) ((dev)->speed)3030-#endif31273228static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)3329{
+559-80
sound/usb/mixer.c
···112112#include "mixer_maps.c"113113114114static const struct usbmix_name_map *115115-find_map(struct mixer_build *state, int unitid, int control)115115+find_map(const struct usbmix_name_map *p, int unitid, int control)116116{117117- const struct usbmix_name_map *p = state->map;118118-119117 if (!p)120118 return NULL;121119122122- for (p = state->map; p->id; p++) {120120+ for (; p->id; p++) {123121 if (p->id == unitid &&124122 (!control || !p->control || control == p->control))125123 return p;···199201/*200202 * copy a string with the given id201203 */202202-static int snd_usb_copy_string_desc(struct mixer_build *state,204204+static int snd_usb_copy_string_desc(struct snd_usb_audio *chip,203205 int index, char *buf, int maxlen)204206{205205- int len = usb_string(state->chip->dev, index, buf, maxlen - 1);207207+ int len = usb_string(chip->dev, index, buf, maxlen - 1);206208207209 if (len < 0)208210 return 0;···598600599601 while (snd_ctl_find_id(mixer->chip->card, &kctl->id))600602 kctl->id.index++;601601- if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {603603+ err = snd_ctl_add(mixer->chip->card, kctl);604604+ if (err < 0) {602605 usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n",603606 err);604607 return err;···657658 { 0 },658659};659660660660-static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm,661661+static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iterm,661662 unsigned char *name, int maxlen, int term_only)662663{663664 struct iterm_name_combo *names;664665 int len;665666666667 if (iterm->name) {667667- len = snd_usb_copy_string_desc(state, iterm->name,668668+ len = snd_usb_copy_string_desc(chip, iterm->name,668669 name, maxlen);669670 if (len)670671 return len;···715716 }716717717718 return 0;719719+}720720+721721+/*722722+ * Get logical cluster information for UAC3 devices.723723+ */724724+static int get_cluster_channels_v3(struct mixer_build *state, unsigned int cluster_id)725725+{726726+ struct uac3_cluster_header_descriptor c_header;727727+ int err;728728+729729+ err = snd_usb_ctl_msg(state->chip->dev,730730+ usb_rcvctrlpipe(state->chip->dev, 0),731731+ UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,732732+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,733733+ cluster_id,734734+ snd_usb_ctrl_intf(state->chip),735735+ &c_header, sizeof(c_header));736736+ if (err < 0)737737+ goto error;738738+ if (err != sizeof(c_header)) {739739+ err = -EIO;740740+ goto error;741741+ }742742+743743+ return c_header.bNrChannels;744744+745745+error:746746+ usb_audio_err(state->chip, "cannot request logical cluster ID: %d (err: %d)\n", cluster_id, err);747747+ return err;748748+}749749+750750+/*751751+ * Get number of channels for a Mixer Unit.752752+ */753753+static int uac_mixer_unit_get_channels(struct mixer_build *state,754754+ struct uac_mixer_unit_descriptor *desc)755755+{756756+ int mu_channels;757757+758758+ if (desc->bLength < 11)759759+ return -EINVAL;760760+ if (!desc->bNrInPins)761761+ return -EINVAL;762762+763763+ switch (state->mixer->protocol) {764764+ case UAC_VERSION_1:765765+ case UAC_VERSION_2:766766+ default:767767+ mu_channels = uac_mixer_unit_bNrChannels(desc);768768+ break;769769+ case UAC_VERSION_3:770770+ mu_channels = get_cluster_channels_v3(state,771771+ uac3_mixer_unit_wClusterDescrID(desc));772772+ break;773773+ }774774+775775+ if (!mu_channels)776776+ return -EINVAL;777777+778778+ return mu_channels;718779}719780720781/*···903844 term->id = id;904845 term->type = le16_to_cpu(d->wTerminalType);905846906906- /* REVISIT: UAC3 IT doesn't have channels/cfg */907907- term->channels = 0;847847+ err = get_cluster_channels_v3(state, le16_to_cpu(d->wClusterDescrID));848848+ if (err < 0)849849+ return err;850850+ term->channels = err;851851+852852+ /* REVISIT: UAC3 IT doesn't have channels cfg */908853 term->chconfig = 0;909854910855 term->name = le16_to_cpu(d->wTerminalDescrStr);···926863 term->type = d->bDescriptorSubtype << 16; /* virtual type */927864 term->id = id;928865 term->name = le16_to_cpu(d->wClockSourceStr);866866+ return 0;867867+ }868868+ case UAC3_MIXER_UNIT: {869869+ struct uac_mixer_unit_descriptor *d = p1;870870+871871+ err = uac_mixer_unit_get_channels(state, d);872872+ if (err < 0)873873+ return err;874874+875875+ term->channels = err;876876+ term->type = d->bDescriptorSubtype << 16; /* virtual type */877877+929878 return 0;930879 }931880 default:···13331258 return 0;13341259}1335126012611261+/* get the connectors status and report it as boolean type */12621262+static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,12631263+ struct snd_ctl_elem_value *ucontrol)12641264+{12651265+ struct usb_mixer_elem_info *cval = kcontrol->private_data;12661266+ struct snd_usb_audio *chip = cval->head.mixer->chip;12671267+ int idx = 0, validx, ret, val;12681268+12691269+ validx = cval->control << 8 | 0;12701270+12711271+ ret = snd_usb_lock_shutdown(chip) ? -EIO : 0;12721272+ if (ret)12731273+ goto error;12741274+12751275+ idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);12761276+ if (cval->head.mixer->protocol == UAC_VERSION_2) {12771277+ struct uac2_connectors_ctl_blk uac2_conn;12781278+12791279+ ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,12801280+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,12811281+ validx, idx, &uac2_conn, sizeof(uac2_conn));12821282+ val = !!uac2_conn.bNrChannels;12831283+ } else { /* UAC_VERSION_3 */12841284+ struct uac3_insertion_ctl_blk uac3_conn;12851285+12861286+ ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,12871287+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,12881288+ validx, idx, &uac3_conn, sizeof(uac3_conn));12891289+ val = !!uac3_conn.bmConInserted;12901290+ }12911291+12921292+ snd_usb_unlock_shutdown(chip);12931293+12941294+ if (ret < 0) {12951295+error:12961296+ usb_audio_err(chip,12971297+ "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",12981298+ UAC_GET_CUR, validx, idx, cval->val_type);12991299+ return ret;13001300+ }13011301+13021302+ ucontrol->value.integer.value[0] = val;13031303+ return 0;13041304+}13051305+13361306static struct snd_kcontrol_new usb_feature_unit_ctl = {13371307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,13381308 .name = "", /* will be filled later manually */···14051285 .access = SNDRV_CTL_ELEM_ACCESS_READ,14061286 .info = snd_ctl_boolean_mono_info,14071287 .get = mixer_ctl_master_bool_get,12881288+ .put = NULL,12891289+};12901290+12911291+static const struct snd_kcontrol_new usb_connector_ctl_ro = {12921292+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,12931293+ .name = "", /* will be filled later manually */12941294+ .access = SNDRV_CTL_ELEM_ACCESS_READ,12951295+ .info = snd_ctl_boolean_mono_info,12961296+ .get = mixer_ctl_connector_get,14081297 .put = NULL,14091298};14101299···14701341 return NULL;14711342}1472134314731473-static void build_feature_ctl(struct mixer_build *state, void *raw_desc,14741474- unsigned int ctl_mask, int control,14751475- struct usb_audio_term *iterm, int unitid,14761476- int readonly_mask)13441344+static void __build_feature_ctl(struct usb_mixer_interface *mixer,13451345+ const struct usbmix_name_map *imap,13461346+ unsigned int ctl_mask, int control,13471347+ struct usb_audio_term *iterm,13481348+ struct usb_audio_term *oterm,13491349+ int unitid, int nameid, int readonly_mask)14771350{14781478- struct uac_feature_unit_descriptor *desc = raw_desc;14791351 struct usb_feature_control_info *ctl_info;14801352 unsigned int len = 0;14811353 int mapped_name = 0;14821482- int nameid = uac_feature_unit_iFeature(desc);14831354 struct snd_kcontrol *kctl;14841355 struct usb_mixer_elem_info *cval;14851356 const struct usbmix_name_map *map;···14901361 return;14911362 }1492136314931493- map = find_map(state, unitid, control);13641364+ map = find_map(imap, unitid, control);14941365 if (check_ignored_ctl(map))14951366 return;1496136714971368 cval = kzalloc(sizeof(*cval), GFP_KERNEL);14981369 if (!cval)14991370 return;15001500- snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);13711371+ snd_usb_mixer_elem_init_std(&cval->head, mixer, unitid);15011372 cval->control = control;15021373 cval->cmask = ctl_mask;15031374···15061377 kfree(cval);15071378 return;15081379 }15091509- if (state->mixer->protocol == UAC_VERSION_1)13801380+ if (mixer->protocol == UAC_VERSION_1)15101381 cval->val_type = ctl_info->type;15111382 else /* UAC_VERSION_2 */15121383 cval->val_type = ctl_info->type_uac2 >= 0 ?···15351406 kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);1536140715371408 if (!kctl) {15381538- usb_audio_err(state->chip, "cannot malloc kcontrol\n");14091409+ usb_audio_err(mixer->chip, "cannot malloc kcontrol\n");15391410 kfree(cval);15401411 return;15411412 }···15441415 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));15451416 mapped_name = len != 0;15461417 if (!len && nameid)15471547- len = snd_usb_copy_string_desc(state, nameid,14181418+ len = snd_usb_copy_string_desc(mixer->chip, nameid,15481419 kctl->id.name, sizeof(kctl->id.name));1549142015501421 switch (control) {···15591430 * - otherwise, anonymous name.15601431 */15611432 if (!len) {15621562- len = get_term_name(state, iterm, kctl->id.name,15631563- sizeof(kctl->id.name), 1);15641564- if (!len)15651565- len = get_term_name(state, &state->oterm,14331433+ if (iterm)14341434+ len = get_term_name(mixer->chip, iterm,14351435+ kctl->id.name,14361436+ sizeof(kctl->id.name), 1);14371437+ if (!len && oterm)14381438+ len = get_term_name(mixer->chip, oterm,15661439 kctl->id.name,15671440 sizeof(kctl->id.name), 1);15681441 if (!len)···15731442 }1574144315751444 if (!mapped_name)15761576- check_no_speaker_on_headset(kctl, state->mixer->chip->card);14451445+ check_no_speaker_on_headset(kctl, mixer->chip->card);1577144615781447 /*15791448 * determine the stream direction:15801449 * if the connected output is USB stream, then it's likely a15811450 * capture stream. otherwise it should be playback (hopefully :)15821451 */15831583- if (!mapped_name && !(state->oterm.type >> 16)) {15841584- if ((state->oterm.type & 0xff00) == 0x0100)14521452+ if (!mapped_name && oterm && !(oterm->type >> 16)) {14531453+ if ((oterm->type & 0xff00) == 0x0100)15851454 append_ctl_name(kctl, " Capture");15861455 else15871456 append_ctl_name(kctl, " Playback");···16091478 }16101479 }1611148016121612- snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl);14811481+ snd_usb_mixer_fu_apply_quirk(mixer, cval, unitid, kctl);1613148216141483 range = (cval->max - cval->min) / cval->res;16151484 /*···16181487 * devices. It will definitively catch all buggy Logitech devices.16191488 */16201489 if (range > 384) {16211621- usb_audio_warn(state->chip,14901490+ usb_audio_warn(mixer->chip,16221491 "Warning! Unlikely big volume range (=%u), cval->res is probably wrong.",16231492 range);16241624- usb_audio_warn(state->chip,14931493+ usb_audio_warn(mixer->chip,16251494 "[%d] FU [%s] ch = %d, val = %d/%d/%d",16261495 cval->head.id, kctl->id.name, cval->channels,16271496 cval->min, cval->max, cval->res);16281497 }1629149816301630- usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",14991499+ usb_audio_dbg(mixer->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",16311500 cval->head.id, kctl->id.name, cval->channels,16321501 cval->min, cval->max, cval->res);16331502 snd_usb_mixer_add_control(&cval->head, kctl);15031503+}15041504+15051505+static void build_feature_ctl(struct mixer_build *state, void *raw_desc,15061506+ unsigned int ctl_mask, int control,15071507+ struct usb_audio_term *iterm, int unitid,15081508+ int readonly_mask)15091509+{15101510+ struct uac_feature_unit_descriptor *desc = raw_desc;15111511+ int nameid = uac_feature_unit_iFeature(desc);15121512+15131513+ __build_feature_ctl(state->mixer, state->map, ctl_mask, control,15141514+ iterm, &state->oterm, unitid, nameid, readonly_mask);15151515+}15161516+15171517+static void build_feature_ctl_badd(struct usb_mixer_interface *mixer,15181518+ unsigned int ctl_mask, int control, int unitid,15191519+ const struct usbmix_name_map *badd_map)15201520+{15211521+ __build_feature_ctl(mixer, badd_map, ctl_mask, control,15221522+ NULL, NULL, unitid, 0, 0);16341523}1635152416361525static void get_connector_control_name(struct mixer_build *state,16371526 struct usb_audio_term *term,16381527 bool is_input, char *name, int name_size)16391528{16401640- int name_len = get_term_name(state, term, name, name_size, 0);15291529+ int name_len = get_term_name(state->chip, term, name, name_size, 0);1641153016421531 if (name_len == 0)16431532 strlcpy(name, "Unknown", name_size);···16851534 return;16861535 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, term->id);16871536 /*16881688- * The first byte from reading the UAC2_TE_CONNECTOR control returns the16891689- * number of channels connected. This boolean ctl will simply report16901690- * if any channels are connected or not.16911691- * (Audio20_final.pdf Table 5-10: Connector Control CUR Parameter Block)15371537+ * UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the15381538+ * number of channels connected.15391539+ *15401540+ * UAC3: The first byte specifies size of bitmap for the inserted controls. The15411541+ * following byte(s) specifies which connectors are inserted.15421542+ *15431543+ * This boolean ctl will simply report if any channels are connected15441544+ * or not.16921545 */16931693- cval->control = UAC2_TE_CONNECTOR;15461546+ if (state->mixer->protocol == UAC_VERSION_2)15471547+ cval->control = UAC2_TE_CONNECTOR;15481548+ else /* UAC_VERSION_3 */15491549+ cval->control = UAC3_TE_INSERTION;15501550+16941551 cval->val_type = USB_MIXER_BOOLEAN;16951552 cval->channels = 1; /* report true if any channel is connected */16961553 cval->min = 0;16971554 cval->max = 1;16981698- kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval);15551555+ kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);16991556 if (!kctl) {17001557 usb_audio_err(state->chip, "cannot malloc kcontrol\n");17011558 kfree(cval);···17641605 }1765160617661607 kctl->private_free = snd_usb_mixer_elem_free;17671767- ret = snd_usb_copy_string_desc(state, hdr->iClockSource,16081608+ ret = snd_usb_copy_string_desc(state->chip, hdr->iClockSource,17681609 name, sizeof(name));17691610 if (ret > 0)17701611 snprintf(kctl->id.name, sizeof(kctl->id.name),···18511692 }1852169318531694 /* parse the source unit */18541854- if ((err = parse_audio_unit(state, hdr->bSourceID)) < 0)16951695+ err = parse_audio_unit(state, hdr->bSourceID);16961696+ if (err < 0)18551697 return err;1856169818571699 /* determine the input source type and name */···19661806 */19671807static void build_mixer_unit_ctl(struct mixer_build *state,19681808 struct uac_mixer_unit_descriptor *desc,19691969- int in_pin, int in_ch, int unitid,19701970- struct usb_audio_term *iterm)18091809+ int in_pin, int in_ch, int num_outs,18101810+ int unitid, struct usb_audio_term *iterm)19711811{19721812 struct usb_mixer_elem_info *cval;19731973- unsigned int num_outs = uac_mixer_unit_bNrChannels(desc);19741813 unsigned int i, len;19751814 struct snd_kcontrol *kctl;19761815 const struct usbmix_name_map *map;1977181619781978- map = find_map(state, unitid, 0);18171817+ map = find_map(state->map, unitid, 0);19791818 if (check_ignored_ctl(map))19801819 return;19811820···2007184820081849 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));20091850 if (!len)20102010- len = get_term_name(state, iterm, kctl->id.name,18511851+ len = get_term_name(state->chip, iterm, kctl->id.name,20111852 sizeof(kctl->id.name), 0);20121853 if (!len)20131854 len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);···20221863 void *raw_desc)20231864{20241865 struct usb_audio_term iterm;20252025- struct uac2_input_terminal_descriptor *d = raw_desc;18661866+ unsigned int control, bmctls, term_id;2026186720272027- check_input_term(state, d->bTerminalID, &iterm);20281868 if (state->mixer->protocol == UAC_VERSION_2) {20292029- /* Check for jack detection. */20302030- if (uac_v2v3_control_is_readable(le16_to_cpu(d->bmControls),20312031- UAC2_TE_CONNECTOR)) {20322032- build_connector_control(state, &iterm, true);20332033- }18691869+ struct uac2_input_terminal_descriptor *d_v2 = raw_desc;18701870+ control = UAC2_TE_CONNECTOR;18711871+ term_id = d_v2->bTerminalID;18721872+ bmctls = le16_to_cpu(d_v2->bmControls);18731873+ } else if (state->mixer->protocol == UAC_VERSION_3) {18741874+ struct uac3_input_terminal_descriptor *d_v3 = raw_desc;18751875+ control = UAC3_TE_INSERTION;18761876+ term_id = d_v3->bTerminalID;18771877+ bmctls = le32_to_cpu(d_v3->bmControls);18781878+ } else {18791879+ return 0; /* UAC1. No Insertion control */20341880 }18811881+18821882+ check_input_term(state, term_id, &iterm);18831883+18841884+ /* Check for jack detection. */18851885+ if (uac_v2v3_control_is_readable(bmctls, control))18861886+ build_connector_control(state, &iterm, true);18871887+20351888 return 0;20361889}20371890···20581887 int input_pins, num_ins, num_outs;20591888 int pin, ich, err;2060188920612061- if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) ||20622062- !(num_outs = uac_mixer_unit_bNrChannels(desc))) {18901890+ err = uac_mixer_unit_get_channels(state, desc);18911891+ if (err < 0) {20631892 usb_audio_err(state->chip,20641893 "invalid MIXER UNIT descriptor %d\n",20651894 unitid);20662066- return -EINVAL;18951895+ return err;20671896 }18971897+18981898+ num_outs = err;18991899+ input_pins = desc->bNrInPins;2068190020691901 num_ins = 0;20701902 ich = 0;···20951921 }20961922 }20971923 if (ich_has_controls)20982098- build_mixer_unit_ctl(state, desc, pin, ich,19241924+ build_mixer_unit_ctl(state, desc, pin, ich, num_outs,20991925 unitid, &iterm);21001926 }21011927 }···22722098 }2273209922742100 for (i = 0; i < num_ins; i++) {22752275- if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)21012101+ err = parse_audio_unit(state, desc->baSourceID[i]);21022102+ if (err < 0)22762103 return err;22772104 }22782105···2289211422902115 if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))22912116 continue;22922292- map = find_map(state, unitid, valinfo->control);21172117+ map = find_map(state->map, unitid, valinfo->control);22932118 if (check_ignored_ctl(map))22942119 continue;22952120 cval = kzalloc(sizeof(*cval), GFP_KERNEL);···23372162 nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);23382163 len = 0;23392164 if (nameid)23402340- len = snd_usb_copy_string_desc(state, nameid,21652165+ len = snd_usb_copy_string_desc(state->chip,21662166+ nameid,23412167 kctl->id.name,23422168 sizeof(kctl->id.name));23432169 if (!len)···24862310 }2487231124882312 for (i = 0; i < desc->bNrInPins; i++) {24892489- if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)23132313+ err = parse_audio_unit(state, desc->baSourceID[i]);23142314+ if (err < 0)24902315 return err;24912316 }2492231724932318 if (desc->bNrInPins == 1) /* only one ? nonsense! */24942319 return 0;2495232024962496- map = find_map(state, unitid, 0);23212321+ map = find_map(state->map, unitid, 0);24972322 if (check_ignored_ctl(map))24982323 return 0;24992324···25352358 len = check_mapped_selector_name(state, unitid, i, namelist[i],25362359 MAX_ITEM_NAME_LEN);25372360 if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0)25382538- len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);23612361+ len = get_term_name(state->chip, &iterm, namelist[i],23622362+ MAX_ITEM_NAME_LEN, 0);25392363 if (! len)25402364 sprintf(namelist[i], "Input %u", i);25412365 }···25582380 /* if iSelector is given, use it */25592381 nameid = uac_selector_unit_iSelector(desc);25602382 if (nameid)25612561- len = snd_usb_copy_string_desc(state, nameid,23832383+ len = snd_usb_copy_string_desc(state->chip, nameid,25622384 kctl->id.name,25632385 sizeof(kctl->id.name));25642386 /* ... or pick up the terminal name at next */25652387 if (!len)25662566- len = get_term_name(state, &state->oterm,23882388+ len = get_term_name(state->chip, &state->oterm,25672389 kctl->id.name, sizeof(kctl->id.name), 0);25682390 /* ... or use the fixed string "USB" as the last resort */25692391 if (!len)···26362458 } else { /* UAC_VERSION_3 */26372459 switch (p1[2]) {26382460 case UAC_INPUT_TERMINAL:26392639- return 0; /* NOP */24612461+ return parse_audio_input_terminal(state, unitid, p1);26402462 case UAC3_MIXER_UNIT:26412463 return parse_audio_mixer_unit(state, unitid, p1);26422464 case UAC3_CLOCK_SOURCE:···26782500{26792501 struct usb_mixer_interface *mixer = device->device_data;26802502 snd_usb_mixer_free(mixer);25032503+ return 0;25042504+}25052505+25062506+/* UAC3 predefined channels configuration */25072507+struct uac3_badd_profile {25082508+ int subclass;25092509+ const char *name;25102510+ int c_chmask; /* capture channels mask */25112511+ int p_chmask; /* playback channels mask */25122512+ int st_chmask; /* side tone mixing channel mask */25132513+};25142514+25152515+static struct uac3_badd_profile uac3_badd_profiles[] = {25162516+ {25172517+ /*25182518+ * BAIF, BAOF or combination of both25192519+ * IN: Mono or Stereo cfg, Mono alt possible25202520+ * OUT: Mono or Stereo cfg, Mono alt possible25212521+ */25222522+ .subclass = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,25232523+ .name = "GENERIC IO",25242524+ .c_chmask = -1, /* dynamic channels */25252525+ .p_chmask = -1, /* dynamic channels */25262526+ },25272527+ {25282528+ /* BAOF; Stereo only cfg, Mono alt possible */25292529+ .subclass = UAC3_FUNCTION_SUBCLASS_HEADPHONE,25302530+ .name = "HEADPHONE",25312531+ .p_chmask = 3,25322532+ },25332533+ {25342534+ /* BAOF; Mono or Stereo cfg, Mono alt possible */25352535+ .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKER,25362536+ .name = "SPEAKER",25372537+ .p_chmask = -1, /* dynamic channels */25382538+ },25392539+ {25402540+ /* BAIF; Mono or Stereo cfg, Mono alt possible */25412541+ .subclass = UAC3_FUNCTION_SUBCLASS_MICROPHONE,25422542+ .name = "MICROPHONE",25432543+ .c_chmask = -1, /* dynamic channels */25442544+ },25452545+ {25462546+ /*25472547+ * BAIOF topology25482548+ * IN: Mono only25492549+ * OUT: Mono or Stereo cfg, Mono alt possible25502550+ */25512551+ .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET,25522552+ .name = "HEADSET",25532553+ .c_chmask = 1,25542554+ .p_chmask = -1, /* dynamic channels */25552555+ .st_chmask = 1,25562556+ },25572557+ {25582558+ /* BAIOF; IN: Mono only; OUT: Stereo only, Mono alt possible */25592559+ .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER,25602560+ .name = "HEADSET ADAPTER",25612561+ .c_chmask = 1,25622562+ .p_chmask = 3,25632563+ .st_chmask = 1,25642564+ },25652565+ {25662566+ /* BAIF + BAOF; IN: Mono only; OUT: Mono only */25672567+ .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,25682568+ .name = "SPEAKERPHONE",25692569+ .c_chmask = 1,25702570+ .p_chmask = 1,25712571+ },25722572+ { 0 } /* terminator */25732573+};25742574+25752575+static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,25762576+ struct uac3_badd_profile *f,25772577+ int c_chmask, int p_chmask)25782578+{25792579+ /*25802580+ * If both playback/capture channels are dynamic, make sure25812581+ * at least one channel is present25822582+ */25832583+ if (f->c_chmask < 0 && f->p_chmask < 0) {25842584+ if (!c_chmask && !p_chmask) {25852585+ usb_audio_warn(mixer->chip, "BAAD %s: no channels?",25862586+ f->name);25872587+ return false;25882588+ }25892589+ return true;25902590+ }25912591+25922592+ if ((f->c_chmask < 0 && !c_chmask) ||25932593+ (f->c_chmask >= 0 && f->c_chmask != c_chmask)) {25942594+ usb_audio_warn(mixer->chip, "BAAD %s c_chmask mismatch",25952595+ f->name);25962596+ return false;25972597+ }25982598+ if ((f->p_chmask < 0 && !p_chmask) ||25992599+ (f->p_chmask >= 0 && f->p_chmask != p_chmask)) {26002600+ usb_audio_warn(mixer->chip, "BAAD %s p_chmask mismatch",26012601+ f->name);26022602+ return false;26032603+ }26042604+ return true;26052605+}26062606+26072607+/*26082608+ * create mixer controls for UAC3 BADD profiles26092609+ *26102610+ * UAC3 BADD device doesn't contain CS descriptors thus we will guess everything26112611+ *26122612+ * BADD device may contain Mixer Unit, which doesn't have any controls, skip it26132613+ */26142614+static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,26152615+ int ctrlif)26162616+{26172617+ struct usb_device *dev = mixer->chip->dev;26182618+ struct usb_interface_assoc_descriptor *assoc;26192619+ int badd_profile = mixer->chip->badd_profile;26202620+ struct uac3_badd_profile *f;26212621+ const struct usbmix_ctl_map *map;26222622+ int p_chmask = 0, c_chmask = 0, st_chmask = 0;26232623+ int i;26242624+26252625+ assoc = usb_ifnum_to_if(dev, ctrlif)->intf_assoc;26262626+26272627+ /* Detect BADD capture/playback channels from AS EP descriptors */26282628+ for (i = 0; i < assoc->bInterfaceCount; i++) {26292629+ int intf = assoc->bFirstInterface + i;26302630+26312631+ struct usb_interface *iface;26322632+ struct usb_host_interface *alts;26332633+ struct usb_interface_descriptor *altsd;26342634+ unsigned int maxpacksize;26352635+ char dir_in;26362636+ int chmask, num;26372637+26382638+ if (intf == ctrlif)26392639+ continue;26402640+26412641+ iface = usb_ifnum_to_if(dev, intf);26422642+ num = iface->num_altsetting;26432643+26442644+ if (num < 2)26452645+ return -EINVAL;26462646+26472647+ /*26482648+ * The number of Channels in an AudioStreaming interface26492649+ * and the audio sample bit resolution (16 bits or 2426502650+ * bits) can be derived from the wMaxPacketSize field in26512651+ * the Standard AS Audio Data Endpoint descriptor in26522652+ * Alternate Setting 126532653+ */26542654+ alts = &iface->altsetting[1];26552655+ altsd = get_iface_desc(alts);26562656+26572657+ if (altsd->bNumEndpoints < 1)26582658+ return -EINVAL;26592659+26602660+ /* check direction */26612661+ dir_in = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);26622662+ maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);26632663+26642664+ switch (maxpacksize) {26652665+ default:26662666+ usb_audio_err(mixer->chip,26672667+ "incorrect wMaxPacketSize 0x%x for BADD profile\n",26682668+ maxpacksize);26692669+ return -EINVAL;26702670+ case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:26712671+ case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:26722672+ case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:26732673+ case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:26742674+ chmask = 1;26752675+ break;26762676+ case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:26772677+ case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:26782678+ case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:26792679+ case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:26802680+ chmask = 3;26812681+ break;26822682+ }26832683+26842684+ if (dir_in)26852685+ c_chmask = chmask;26862686+ else26872687+ p_chmask = chmask;26882688+ }26892689+26902690+ usb_audio_dbg(mixer->chip,26912691+ "UAC3 BADD profile 0x%x: detected c_chmask=%d p_chmask=%d\n",26922692+ badd_profile, c_chmask, p_chmask);26932693+26942694+ /* check the mapping table */26952695+ for (map = uac3_badd_usbmix_ctl_maps; map->id; map++) {26962696+ if (map->id == badd_profile)26972697+ break;26982698+ }26992699+27002700+ if (!map->id)27012701+ return -EINVAL;27022702+27032703+ for (f = uac3_badd_profiles; f->name; f++) {27042704+ if (badd_profile == f->subclass)27052705+ break;27062706+ }27072707+ if (!f->name)27082708+ return -EINVAL;27092709+ if (!uac3_badd_func_has_valid_channels(mixer, f, c_chmask, p_chmask))27102710+ return -EINVAL;27112711+ st_chmask = f->st_chmask;27122712+27132713+ /* Playback */27142714+ if (p_chmask) {27152715+ /* Master channel, always writable */27162716+ build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,27172717+ UAC3_BADD_FU_ID2, map->map);27182718+ /* Mono/Stereo volume channels, always writable */27192719+ build_feature_ctl_badd(mixer, p_chmask, UAC_FU_VOLUME,27202720+ UAC3_BADD_FU_ID2, map->map);27212721+ }27222722+27232723+ /* Capture */27242724+ if (c_chmask) {27252725+ /* Master channel, always writable */27262726+ build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,27272727+ UAC3_BADD_FU_ID5, map->map);27282728+ /* Mono/Stereo volume channels, always writable */27292729+ build_feature_ctl_badd(mixer, c_chmask, UAC_FU_VOLUME,27302730+ UAC3_BADD_FU_ID5, map->map);27312731+ }27322732+27332733+ /* Side tone-mixing */27342734+ if (st_chmask) {27352735+ /* Master channel, always writable */27362736+ build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,27372737+ UAC3_BADD_FU_ID7, map->map);27382738+ /* Mono volume channel, always writable */27392739+ build_feature_ctl_badd(mixer, 1, UAC_FU_VOLUME,27402740+ UAC3_BADD_FU_ID7, map->map);27412741+ }27422742+26812743 return 0;26822744}26832745···30142596 err = parse_audio_unit(&state, desc->bCSourceID);30152597 if (err < 0 && err != -EINVAL)30162598 return err;25992599+26002600+ if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),26012601+ UAC3_TE_INSERTION)) {26022602+ build_connector_control(&state, &state.oterm,26032603+ false);26042604+ }30172605 }30182606 }30192607···30302606{30312607 struct usb_mixer_elem_list *list;3032260830333033- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {26092609+ for_each_mixer_elem(list, mixer, unitid) {30342610 struct usb_mixer_elem_info *info =30353035- (struct usb_mixer_elem_info *)list;26112611+ mixer_elem_list_to_info(list);30362612 /* invalidate cache, so the value is read from the device */30372613 info->cached = 0;30382614 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,···30432619static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,30442620 struct usb_mixer_elem_list *list)30452621{30463046- struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;26222622+ struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);30472623 static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",30482624 "S8", "U8", "S16", "U16"};30492625 snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "···30692645 mixer->ignore_ctl_error);30702646 snd_iprintf(buffer, "Card: %s\n", chip->card->longname);30712647 for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {30723072- for (list = mixer->id_elems[unitid]; list;30733073- list = list->next_id_elem) {26482648+ for_each_mixer_elem(list, mixer, unitid) {30742649 snd_iprintf(buffer, " Unit: %i\n", list->id);30752650 if (list->kctl)30762651 snd_iprintf(buffer,···30992676 return;31002677 }3101267831023102- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)26792679+ for_each_mixer_elem(list, mixer, unitid)31032680 count++;3104268131052682 if (count == 0)31062683 return;3107268431083108- for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {26852685+ for_each_mixer_elem(list, mixer, unitid) {31092686 struct usb_mixer_elem_info *info;3110268731112688 if (!list->kctl)31122689 continue;3113269031143114- info = (struct usb_mixer_elem_info *)list;26912691+ info = mixer_elem_list_to_info(list);31152692 if (count > 1 && info->control != control)31162693 continue;31172694···32322809 return 0;32332810}3234281128122812+static int keep_iface_ctl_get(struct snd_kcontrol *kcontrol,28132813+ struct snd_ctl_elem_value *ucontrol)28142814+{28152815+ struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);28162816+28172817+ ucontrol->value.integer.value[0] = mixer->chip->keep_iface;28182818+ return 0;28192819+}28202820+28212821+static int keep_iface_ctl_put(struct snd_kcontrol *kcontrol,28222822+ struct snd_ctl_elem_value *ucontrol)28232823+{28242824+ struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);28252825+ bool keep_iface = !!ucontrol->value.integer.value[0];28262826+28272827+ if (mixer->chip->keep_iface == keep_iface)28282828+ return 0;28292829+ mixer->chip->keep_iface = keep_iface;28302830+ return 1;28312831+}28322832+28332833+static const struct snd_kcontrol_new keep_iface_ctl = {28342834+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,28352835+ .name = "Keep Interface",28362836+ .info = snd_ctl_boolean_mono_info,28372837+ .get = keep_iface_ctl_get,28382838+ .put = keep_iface_ctl_put,28392839+};28402840+28412841+static int create_keep_iface_ctl(struct usb_mixer_interface *mixer)28422842+{28432843+ struct snd_kcontrol *kctl = snd_ctl_new1(&keep_iface_ctl, mixer);28442844+28452845+ /* need only one control per card */28462846+ if (snd_ctl_find_id(mixer->chip->card, &kctl->id)) {28472847+ snd_ctl_free_one(kctl);28482848+ return 0;28492849+ }28502850+28512851+ return snd_ctl_add(mixer->chip->card, kctl);28522852+}28532853+32352854int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,32362855 int ignore_error)32372856{···33122847 break;33132848 }3314284933153315- if ((err = snd_usb_mixer_controls(mixer)) < 0 ||33163316- (err = snd_usb_mixer_status_create(mixer)) < 0)28502850+ if (mixer->protocol == UAC_VERSION_3 &&28512851+ chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {28522852+ err = snd_usb_mixer_controls_badd(mixer, ctrlif);28532853+ if (err < 0)28542854+ goto _error;28552855+ } else {28562856+ err = snd_usb_mixer_controls(mixer);28572857+ if (err < 0)28582858+ goto _error;28592859+ err = snd_usb_mixer_status_create(mixer);28602860+ if (err < 0)28612861+ goto _error;28622862+ }28632863+ err = create_keep_iface_ctl(mixer);28642864+ if (err < 0)33172865 goto _error;3318286633192867 snd_usb_mixer_apply_create_quirk(mixer);···3387290933882910static int restore_mixer_value(struct usb_mixer_elem_list *list)33892911{33903390- struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;29122912+ struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);33912913 int c, err, idx;3392291433932915 if (cval->cmask) {···34232945 if (reset_resume) {34242946 /* restore cached mixer values */34252947 for (id = 0; id < MAX_ID_ELEMS; id++) {34263426- for (list = mixer->id_elems[id]; list;34273427- list = list->next_id_elem) {29482948+ for_each_mixer_elem(list, mixer, id) {34282949 if (list->resume) {34292950 err = list->resume(list);34302951 if (err < 0)···34322955 }34332956 }34342957 }29582958+29592959+ snd_usb_mixer_resume_quirk(mixer);3435296034362961 return snd_usb_mixer_activate(mixer);34372962}
+6
sound/usb/mixer.h
···5353 usb_mixer_elem_resume_func_t resume;5454};55555656+/* iterate over mixer element list of the given unit id */5757+#define for_each_mixer_elem(list, mixer, id) \5858+ for ((list) = (mixer)->id_elems[id]; (list); (list) = (list)->next_id_elem)5959+#define mixer_elem_list_to_info(list) \6060+ container_of(list, struct usb_mixer_elem_info, head)6161+5662struct usb_mixer_elem_info {5763 struct usb_mixer_elem_list head;5864 unsigned int control; /* CS or ICN (high byte) */
···11+// SPDX-License-Identifier: GPL-2.0 OR MIT22+33+/*44+ * Xen para-virtual sound device55+ *66+ * Copyright (C) 2016-2018 EPAM Systems Inc.77+ *88+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>99+ */1010+1111+#include <xen/xenbus.h>1212+1313+#include <xen/interface/io/sndif.h>1414+1515+#include "xen_snd_front.h"1616+#include "xen_snd_front_cfg.h"1717+1818+/* Maximum number of supported streams. */1919+#define VSND_MAX_STREAM 82020+2121+struct cfg_hw_sample_rate {2222+ const char *name;2323+ unsigned int mask;2424+ unsigned int value;2525+};2626+2727+static const struct cfg_hw_sample_rate CFG_HW_SUPPORTED_RATES[] = {2828+ { .name = "5512", .mask = SNDRV_PCM_RATE_5512, .value = 5512 },2929+ { .name = "8000", .mask = SNDRV_PCM_RATE_8000, .value = 8000 },3030+ { .name = "11025", .mask = SNDRV_PCM_RATE_11025, .value = 11025 },3131+ { .name = "16000", .mask = SNDRV_PCM_RATE_16000, .value = 16000 },3232+ { .name = "22050", .mask = SNDRV_PCM_RATE_22050, .value = 22050 },3333+ { .name = "32000", .mask = SNDRV_PCM_RATE_32000, .value = 32000 },3434+ { .name = "44100", .mask = SNDRV_PCM_RATE_44100, .value = 44100 },3535+ { .name = "48000", .mask = SNDRV_PCM_RATE_48000, .value = 48000 },3636+ { .name = "64000", .mask = SNDRV_PCM_RATE_64000, .value = 64000 },3737+ { .name = "96000", .mask = SNDRV_PCM_RATE_96000, .value = 96000 },3838+ { .name = "176400", .mask = SNDRV_PCM_RATE_176400, .value = 176400 },3939+ { .name = "192000", .mask = SNDRV_PCM_RATE_192000, .value = 192000 },4040+};4141+4242+struct cfg_hw_sample_format {4343+ const char *name;4444+ u64 mask;4545+};4646+4747+static const struct cfg_hw_sample_format CFG_HW_SUPPORTED_FORMATS[] = {4848+ {4949+ .name = XENSND_PCM_FORMAT_U8_STR,5050+ .mask = SNDRV_PCM_FMTBIT_U85151+ },5252+ {5353+ .name = XENSND_PCM_FORMAT_S8_STR,5454+ .mask = SNDRV_PCM_FMTBIT_S85555+ },5656+ {5757+ .name = XENSND_PCM_FORMAT_U16_LE_STR,5858+ .mask = SNDRV_PCM_FMTBIT_U16_LE5959+ },6060+ {6161+ .name = XENSND_PCM_FORMAT_U16_BE_STR,6262+ .mask = SNDRV_PCM_FMTBIT_U16_BE6363+ },6464+ {6565+ .name = XENSND_PCM_FORMAT_S16_LE_STR,6666+ .mask = SNDRV_PCM_FMTBIT_S16_LE6767+ },6868+ {6969+ .name = XENSND_PCM_FORMAT_S16_BE_STR,7070+ .mask = SNDRV_PCM_FMTBIT_S16_BE7171+ },7272+ {7373+ .name = XENSND_PCM_FORMAT_U24_LE_STR,7474+ .mask = SNDRV_PCM_FMTBIT_U24_LE7575+ },7676+ {7777+ .name = XENSND_PCM_FORMAT_U24_BE_STR,7878+ .mask = SNDRV_PCM_FMTBIT_U24_BE7979+ },8080+ {8181+ .name = XENSND_PCM_FORMAT_S24_LE_STR,8282+ .mask = SNDRV_PCM_FMTBIT_S24_LE8383+ },8484+ {8585+ .name = XENSND_PCM_FORMAT_S24_BE_STR,8686+ .mask = SNDRV_PCM_FMTBIT_S24_BE8787+ },8888+ {8989+ .name = XENSND_PCM_FORMAT_U32_LE_STR,9090+ .mask = SNDRV_PCM_FMTBIT_U32_LE9191+ },9292+ {9393+ .name = XENSND_PCM_FORMAT_U32_BE_STR,9494+ .mask = SNDRV_PCM_FMTBIT_U32_BE9595+ },9696+ {9797+ .name = XENSND_PCM_FORMAT_S32_LE_STR,9898+ .mask = SNDRV_PCM_FMTBIT_S32_LE9999+ },100100+ {101101+ .name = XENSND_PCM_FORMAT_S32_BE_STR,102102+ .mask = SNDRV_PCM_FMTBIT_S32_BE103103+ },104104+ {105105+ .name = XENSND_PCM_FORMAT_A_LAW_STR,106106+ .mask = SNDRV_PCM_FMTBIT_A_LAW107107+ },108108+ {109109+ .name = XENSND_PCM_FORMAT_MU_LAW_STR,110110+ .mask = SNDRV_PCM_FMTBIT_MU_LAW111111+ },112112+ {113113+ .name = XENSND_PCM_FORMAT_F32_LE_STR,114114+ .mask = SNDRV_PCM_FMTBIT_FLOAT_LE115115+ },116116+ {117117+ .name = XENSND_PCM_FORMAT_F32_BE_STR,118118+ .mask = SNDRV_PCM_FMTBIT_FLOAT_BE119119+ },120120+ {121121+ .name = XENSND_PCM_FORMAT_F64_LE_STR,122122+ .mask = SNDRV_PCM_FMTBIT_FLOAT64_LE123123+ },124124+ {125125+ .name = XENSND_PCM_FORMAT_F64_BE_STR,126126+ .mask = SNDRV_PCM_FMTBIT_FLOAT64_BE127127+ },128128+ {129129+ .name = XENSND_PCM_FORMAT_IEC958_SUBFRAME_LE_STR,130130+ .mask = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE131131+ },132132+ {133133+ .name = XENSND_PCM_FORMAT_IEC958_SUBFRAME_BE_STR,134134+ .mask = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE135135+ },136136+ {137137+ .name = XENSND_PCM_FORMAT_IMA_ADPCM_STR,138138+ .mask = SNDRV_PCM_FMTBIT_IMA_ADPCM139139+ },140140+ {141141+ .name = XENSND_PCM_FORMAT_MPEG_STR,142142+ .mask = SNDRV_PCM_FMTBIT_MPEG143143+ },144144+ {145145+ .name = XENSND_PCM_FORMAT_GSM_STR,146146+ .mask = SNDRV_PCM_FMTBIT_GSM147147+ },148148+};149149+150150+static void cfg_hw_rates(char *list, unsigned int len,151151+ const char *path, struct snd_pcm_hardware *pcm_hw)152152+{153153+ char *cur_rate;154154+ unsigned int cur_mask;155155+ unsigned int cur_value;156156+ unsigned int rates;157157+ unsigned int rate_min;158158+ unsigned int rate_max;159159+ int i;160160+161161+ rates = 0;162162+ rate_min = -1;163163+ rate_max = 0;164164+ while ((cur_rate = strsep(&list, XENSND_LIST_SEPARATOR))) {165165+ for (i = 0; i < ARRAY_SIZE(CFG_HW_SUPPORTED_RATES); i++)166166+ if (!strncasecmp(cur_rate,167167+ CFG_HW_SUPPORTED_RATES[i].name,168168+ XENSND_SAMPLE_RATE_MAX_LEN)) {169169+ cur_mask = CFG_HW_SUPPORTED_RATES[i].mask;170170+ cur_value = CFG_HW_SUPPORTED_RATES[i].value;171171+ rates |= cur_mask;172172+ if (rate_min > cur_value)173173+ rate_min = cur_value;174174+ if (rate_max < cur_value)175175+ rate_max = cur_value;176176+ }177177+ }178178+179179+ if (rates) {180180+ pcm_hw->rates = rates;181181+ pcm_hw->rate_min = rate_min;182182+ pcm_hw->rate_max = rate_max;183183+ }184184+}185185+186186+static void cfg_formats(char *list, unsigned int len,187187+ const char *path, struct snd_pcm_hardware *pcm_hw)188188+{189189+ u64 formats;190190+ char *cur_format;191191+ int i;192192+193193+ formats = 0;194194+ while ((cur_format = strsep(&list, XENSND_LIST_SEPARATOR))) {195195+ for (i = 0; i < ARRAY_SIZE(CFG_HW_SUPPORTED_FORMATS); i++)196196+ if (!strncasecmp(cur_format,197197+ CFG_HW_SUPPORTED_FORMATS[i].name,198198+ XENSND_SAMPLE_FORMAT_MAX_LEN))199199+ formats |= CFG_HW_SUPPORTED_FORMATS[i].mask;200200+ }201201+202202+ if (formats)203203+ pcm_hw->formats = formats;204204+}205205+206206+#define MAX_BUFFER_SIZE (64 * 1024)207207+#define MIN_PERIOD_SIZE 64208208+#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE209209+#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | \210210+ SNDRV_PCM_FMTBIT_S16_LE)211211+#define USE_RATE (SNDRV_PCM_RATE_CONTINUOUS | \212212+ SNDRV_PCM_RATE_8000_48000)213213+#define USE_RATE_MIN 5512214214+#define USE_RATE_MAX 48000215215+#define USE_CHANNELS_MIN 1216216+#define USE_CHANNELS_MAX 2217217+#define USE_PERIODS_MIN 2218218+#define USE_PERIODS_MAX (MAX_BUFFER_SIZE / MIN_PERIOD_SIZE)219219+220220+static const struct snd_pcm_hardware SND_DRV_PCM_HW_DEFAULT = {221221+ .info = (SNDRV_PCM_INFO_MMAP |222222+ SNDRV_PCM_INFO_INTERLEAVED |223223+ SNDRV_PCM_INFO_RESUME |224224+ SNDRV_PCM_INFO_MMAP_VALID),225225+ .formats = USE_FORMATS,226226+ .rates = USE_RATE,227227+ .rate_min = USE_RATE_MIN,228228+ .rate_max = USE_RATE_MAX,229229+ .channels_min = USE_CHANNELS_MIN,230230+ .channels_max = USE_CHANNELS_MAX,231231+ .buffer_bytes_max = MAX_BUFFER_SIZE,232232+ .period_bytes_min = MIN_PERIOD_SIZE,233233+ .period_bytes_max = MAX_PERIOD_SIZE,234234+ .periods_min = USE_PERIODS_MIN,235235+ .periods_max = USE_PERIODS_MAX,236236+ .fifo_size = 0,237237+};238238+239239+static void cfg_read_pcm_hw(const char *path,240240+ struct snd_pcm_hardware *parent_pcm_hw,241241+ struct snd_pcm_hardware *pcm_hw)242242+{243243+ char *list;244244+ int val;245245+ size_t buf_sz;246246+ unsigned int len;247247+248248+ /* Inherit parent's PCM HW and read overrides from XenStore. */249249+ if (parent_pcm_hw)250250+ *pcm_hw = *parent_pcm_hw;251251+ else252252+ *pcm_hw = SND_DRV_PCM_HW_DEFAULT;253253+254254+ val = xenbus_read_unsigned(path, XENSND_FIELD_CHANNELS_MIN, 0);255255+ if (val)256256+ pcm_hw->channels_min = val;257257+258258+ val = xenbus_read_unsigned(path, XENSND_FIELD_CHANNELS_MAX, 0);259259+ if (val)260260+ pcm_hw->channels_max = val;261261+262262+ list = xenbus_read(XBT_NIL, path, XENSND_FIELD_SAMPLE_RATES, &len);263263+ if (!IS_ERR(list)) {264264+ cfg_hw_rates(list, len, path, pcm_hw);265265+ kfree(list);266266+ }267267+268268+ list = xenbus_read(XBT_NIL, path, XENSND_FIELD_SAMPLE_FORMATS, &len);269269+ if (!IS_ERR(list)) {270270+ cfg_formats(list, len, path, pcm_hw);271271+ kfree(list);272272+ }273273+274274+ buf_sz = xenbus_read_unsigned(path, XENSND_FIELD_BUFFER_SIZE, 0);275275+ if (buf_sz)276276+ pcm_hw->buffer_bytes_max = buf_sz;277277+278278+ /* Update configuration to match new values. */279279+ if (pcm_hw->channels_min > pcm_hw->channels_max)280280+ pcm_hw->channels_min = pcm_hw->channels_max;281281+282282+ if (pcm_hw->rate_min > pcm_hw->rate_max)283283+ pcm_hw->rate_min = pcm_hw->rate_max;284284+285285+ pcm_hw->period_bytes_max = pcm_hw->buffer_bytes_max;286286+287287+ pcm_hw->periods_max = pcm_hw->period_bytes_max /288288+ pcm_hw->period_bytes_min;289289+}290290+291291+static int cfg_get_stream_type(const char *path, int index,292292+ int *num_pb, int *num_cap)293293+{294294+ char *str = NULL;295295+ char *stream_path;296296+ int ret;297297+298298+ *num_pb = 0;299299+ *num_cap = 0;300300+ stream_path = kasprintf(GFP_KERNEL, "%s/%d", path, index);301301+ if (!stream_path) {302302+ ret = -ENOMEM;303303+ goto fail;304304+ }305305+306306+ str = xenbus_read(XBT_NIL, stream_path, XENSND_FIELD_TYPE, NULL);307307+ if (IS_ERR(str)) {308308+ ret = PTR_ERR(str);309309+ str = NULL;310310+ goto fail;311311+ }312312+313313+ if (!strncasecmp(str, XENSND_STREAM_TYPE_PLAYBACK,314314+ sizeof(XENSND_STREAM_TYPE_PLAYBACK))) {315315+ (*num_pb)++;316316+ } else if (!strncasecmp(str, XENSND_STREAM_TYPE_CAPTURE,317317+ sizeof(XENSND_STREAM_TYPE_CAPTURE))) {318318+ (*num_cap)++;319319+ } else {320320+ ret = -EINVAL;321321+ goto fail;322322+ }323323+ ret = 0;324324+325325+fail:326326+ kfree(stream_path);327327+ kfree(str);328328+ return ret;329329+}330330+331331+static int cfg_stream(struct xen_snd_front_info *front_info,332332+ struct xen_front_cfg_pcm_instance *pcm_instance,333333+ const char *path, int index, int *cur_pb, int *cur_cap,334334+ int *stream_cnt)335335+{336336+ char *str = NULL;337337+ char *stream_path;338338+ struct xen_front_cfg_stream *stream;339339+ int ret;340340+341341+ stream_path = devm_kasprintf(&front_info->xb_dev->dev,342342+ GFP_KERNEL, "%s/%d", path, index);343343+ if (!stream_path) {344344+ ret = -ENOMEM;345345+ goto fail;346346+ }347347+348348+ str = xenbus_read(XBT_NIL, stream_path, XENSND_FIELD_TYPE, NULL);349349+ if (IS_ERR(str)) {350350+ ret = PTR_ERR(str);351351+ str = NULL;352352+ goto fail;353353+ }354354+355355+ if (!strncasecmp(str, XENSND_STREAM_TYPE_PLAYBACK,356356+ sizeof(XENSND_STREAM_TYPE_PLAYBACK))) {357357+ stream = &pcm_instance->streams_pb[(*cur_pb)++];358358+ } else if (!strncasecmp(str, XENSND_STREAM_TYPE_CAPTURE,359359+ sizeof(XENSND_STREAM_TYPE_CAPTURE))) {360360+ stream = &pcm_instance->streams_cap[(*cur_cap)++];361361+ } else {362362+ ret = -EINVAL;363363+ goto fail;364364+ }365365+366366+ /* Get next stream index. */367367+ stream->index = (*stream_cnt)++;368368+ stream->xenstore_path = stream_path;369369+ /*370370+ * Check XenStore if PCM HW configuration exists for this stream371371+ * and update if so, e.g. we inherit all values from device's PCM HW,372372+ * but can still override some of the values for the stream.373373+ */374374+ cfg_read_pcm_hw(stream->xenstore_path,375375+ &pcm_instance->pcm_hw, &stream->pcm_hw);376376+ ret = 0;377377+378378+fail:379379+ kfree(str);380380+ return ret;381381+}382382+383383+static int cfg_device(struct xen_snd_front_info *front_info,384384+ struct xen_front_cfg_pcm_instance *pcm_instance,385385+ struct snd_pcm_hardware *parent_pcm_hw,386386+ const char *path, int node_index, int *stream_cnt)387387+{388388+ char *str;389389+ char *device_path;390390+ int ret, i, num_streams;391391+ int num_pb, num_cap;392392+ int cur_pb, cur_cap;393393+ char node[3];394394+395395+ device_path = kasprintf(GFP_KERNEL, "%s/%d", path, node_index);396396+ if (!device_path)397397+ return -ENOMEM;398398+399399+ str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL);400400+ if (!IS_ERR(str)) {401401+ strlcpy(pcm_instance->name, str, sizeof(pcm_instance->name));402402+ kfree(str);403403+ }404404+405405+ pcm_instance->device_id = node_index;406406+407407+ /*408408+ * Check XenStore if PCM HW configuration exists for this device409409+ * and update if so, e.g. we inherit all values from card's PCM HW,410410+ * but can still override some of the values for the device.411411+ */412412+ cfg_read_pcm_hw(device_path, parent_pcm_hw, &pcm_instance->pcm_hw);413413+414414+ /* Find out how many streams were configured in Xen store. */415415+ num_streams = 0;416416+ do {417417+ snprintf(node, sizeof(node), "%d", num_streams);418418+ if (!xenbus_exists(XBT_NIL, device_path, node))419419+ break;420420+421421+ num_streams++;422422+ } while (num_streams < VSND_MAX_STREAM);423423+424424+ pcm_instance->num_streams_pb = 0;425425+ pcm_instance->num_streams_cap = 0;426426+ /* Get number of playback and capture streams. */427427+ for (i = 0; i < num_streams; i++) {428428+ ret = cfg_get_stream_type(device_path, i, &num_pb, &num_cap);429429+ if (ret < 0)430430+ goto fail;431431+432432+ pcm_instance->num_streams_pb += num_pb;433433+ pcm_instance->num_streams_cap += num_cap;434434+ }435435+436436+ if (pcm_instance->num_streams_pb) {437437+ pcm_instance->streams_pb =438438+ devm_kcalloc(&front_info->xb_dev->dev,439439+ pcm_instance->num_streams_pb,440440+ sizeof(struct xen_front_cfg_stream),441441+ GFP_KERNEL);442442+ if (!pcm_instance->streams_pb) {443443+ ret = -ENOMEM;444444+ goto fail;445445+ }446446+ }447447+448448+ if (pcm_instance->num_streams_cap) {449449+ pcm_instance->streams_cap =450450+ devm_kcalloc(&front_info->xb_dev->dev,451451+ pcm_instance->num_streams_cap,452452+ sizeof(struct xen_front_cfg_stream),453453+ GFP_KERNEL);454454+ if (!pcm_instance->streams_cap) {455455+ ret = -ENOMEM;456456+ goto fail;457457+ }458458+ }459459+460460+ cur_pb = 0;461461+ cur_cap = 0;462462+ for (i = 0; i < num_streams; i++) {463463+ ret = cfg_stream(front_info, pcm_instance, device_path, i,464464+ &cur_pb, &cur_cap, stream_cnt);465465+ if (ret < 0)466466+ goto fail;467467+ }468468+ ret = 0;469469+470470+fail:471471+ kfree(device_path);472472+ return ret;473473+}474474+475475+int xen_snd_front_cfg_card(struct xen_snd_front_info *front_info,476476+ int *stream_cnt)477477+{478478+ struct xenbus_device *xb_dev = front_info->xb_dev;479479+ struct xen_front_cfg_card *cfg = &front_info->cfg;480480+ int ret, num_devices, i;481481+ char node[3];482482+483483+ *stream_cnt = 0;484484+ num_devices = 0;485485+ do {486486+ snprintf(node, sizeof(node), "%d", num_devices);487487+ if (!xenbus_exists(XBT_NIL, xb_dev->nodename, node))488488+ break;489489+490490+ num_devices++;491491+ } while (num_devices < SNDRV_PCM_DEVICES);492492+493493+ if (!num_devices) {494494+ dev_warn(&xb_dev->dev,495495+ "No devices configured for sound card at %s\n",496496+ xb_dev->nodename);497497+ return -ENODEV;498498+ }499499+500500+ /* Start from default PCM HW configuration for the card. */501501+ cfg_read_pcm_hw(xb_dev->nodename, NULL, &cfg->pcm_hw);502502+503503+ cfg->pcm_instances =504504+ devm_kcalloc(&front_info->xb_dev->dev, num_devices,505505+ sizeof(struct xen_front_cfg_pcm_instance),506506+ GFP_KERNEL);507507+ if (!cfg->pcm_instances)508508+ return -ENOMEM;509509+510510+ for (i = 0; i < num_devices; i++) {511511+ ret = cfg_device(front_info, &cfg->pcm_instances[i],512512+ &cfg->pcm_hw, xb_dev->nodename, i, stream_cnt);513513+ if (ret < 0)514514+ return ret;515515+ }516516+ cfg->num_pcm_instances = num_devices;517517+ return 0;518518+}519519+
+46
sound/xen/xen_snd_front_cfg.h
···11+/* SPDX-License-Identifier: GPL-2.0 OR MIT */22+33+/*44+ * Xen para-virtual sound device55+ *66+ * Copyright (C) 2016-2018 EPAM Systems Inc.77+ *88+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>99+ */1010+1111+#ifndef __XEN_SND_FRONT_CFG_H1212+#define __XEN_SND_FRONT_CFG_H1313+1414+#include <sound/core.h>1515+#include <sound/pcm.h>1616+1717+struct xen_snd_front_info;1818+1919+struct xen_front_cfg_stream {2020+ int index;2121+ char *xenstore_path;2222+ struct snd_pcm_hardware pcm_hw;2323+};2424+2525+struct xen_front_cfg_pcm_instance {2626+ char name[80];2727+ int device_id;2828+ struct snd_pcm_hardware pcm_hw;2929+ int num_streams_pb;3030+ struct xen_front_cfg_stream *streams_pb;3131+ int num_streams_cap;3232+ struct xen_front_cfg_stream *streams_cap;3333+};3434+3535+struct xen_front_cfg_card {3636+ char name_short[32];3737+ char name_long[80];3838+ struct snd_pcm_hardware pcm_hw;3939+ int num_pcm_instances;4040+ struct xen_front_cfg_pcm_instance *pcm_instances;4141+};4242+4343+int xen_snd_front_cfg_card(struct xen_snd_front_info *front_info,4444+ int *stream_cnt);4545+4646+#endif /* __XEN_SND_FRONT_CFG_H */
+494
sound/xen/xen_snd_front_evtchnl.c
···11+// SPDX-License-Identifier: GPL-2.0 OR MIT22+33+/*44+ * Xen para-virtual sound device55+ *66+ * Copyright (C) 2016-2018 EPAM Systems Inc.77+ *88+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>99+ */1010+1111+#include <xen/events.h>1212+#include <xen/grant_table.h>1313+#include <xen/xen.h>1414+#include <xen/xenbus.h>1515+1616+#include "xen_snd_front.h"1717+#include "xen_snd_front_alsa.h"1818+#include "xen_snd_front_cfg.h"1919+#include "xen_snd_front_evtchnl.h"2020+2121+static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id)2222+{2323+ struct xen_snd_front_evtchnl *channel = dev_id;2424+ struct xen_snd_front_info *front_info = channel->front_info;2525+ struct xensnd_resp *resp;2626+ RING_IDX i, rp;2727+2828+ if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED))2929+ return IRQ_HANDLED;3030+3131+ mutex_lock(&channel->ring_io_lock);3232+3333+again:3434+ rp = channel->u.req.ring.sring->rsp_prod;3535+ /* Ensure we see queued responses up to rp. */3636+ rmb();3737+3838+ /*3939+ * Assume that the backend is trusted to always write sane values4040+ * to the ring counters, so no overflow checks on frontend side4141+ * are required.4242+ */4343+ for (i = channel->u.req.ring.rsp_cons; i != rp; i++) {4444+ resp = RING_GET_RESPONSE(&channel->u.req.ring, i);4545+ if (resp->id != channel->evt_id)4646+ continue;4747+ switch (resp->operation) {4848+ case XENSND_OP_OPEN:4949+ /* fall through */5050+ case XENSND_OP_CLOSE:5151+ /* fall through */5252+ case XENSND_OP_READ:5353+ /* fall through */5454+ case XENSND_OP_WRITE:5555+ /* fall through */5656+ case XENSND_OP_TRIGGER:5757+ channel->u.req.resp_status = resp->status;5858+ complete(&channel->u.req.completion);5959+ break;6060+ case XENSND_OP_HW_PARAM_QUERY:6161+ channel->u.req.resp_status = resp->status;6262+ channel->u.req.resp.hw_param =6363+ resp->resp.hw_param;6464+ complete(&channel->u.req.completion);6565+ break;6666+6767+ default:6868+ dev_err(&front_info->xb_dev->dev,6969+ "Operation %d is not supported\n",7070+ resp->operation);7171+ break;7272+ }7373+ }7474+7575+ channel->u.req.ring.rsp_cons = i;7676+ if (i != channel->u.req.ring.req_prod_pvt) {7777+ int more_to_do;7878+7979+ RING_FINAL_CHECK_FOR_RESPONSES(&channel->u.req.ring,8080+ more_to_do);8181+ if (more_to_do)8282+ goto again;8383+ } else {8484+ channel->u.req.ring.sring->rsp_event = i + 1;8585+ }8686+8787+ mutex_unlock(&channel->ring_io_lock);8888+ return IRQ_HANDLED;8989+}9090+9191+static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id)9292+{9393+ struct xen_snd_front_evtchnl *channel = dev_id;9494+ struct xensnd_event_page *page = channel->u.evt.page;9595+ u32 cons, prod;9696+9797+ if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED))9898+ return IRQ_HANDLED;9999+100100+ mutex_lock(&channel->ring_io_lock);101101+102102+ prod = page->in_prod;103103+ /* Ensure we see ring contents up to prod. */104104+ virt_rmb();105105+ if (prod == page->in_cons)106106+ goto out;107107+108108+ /*109109+ * Assume that the backend is trusted to always write sane values110110+ * to the ring counters, so no overflow checks on frontend side111111+ * are required.112112+ */113113+ for (cons = page->in_cons; cons != prod; cons++) {114114+ struct xensnd_evt *event;115115+116116+ event = &XENSND_IN_RING_REF(page, cons);117117+ if (unlikely(event->id != channel->evt_id++))118118+ continue;119119+120120+ switch (event->type) {121121+ case XENSND_EVT_CUR_POS:122122+ xen_snd_front_alsa_handle_cur_pos(channel,123123+ event->op.cur_pos.position);124124+ break;125125+ }126126+ }127127+128128+ page->in_cons = cons;129129+ /* Ensure ring contents. */130130+ virt_wmb();131131+132132+out:133133+ mutex_unlock(&channel->ring_io_lock);134134+ return IRQ_HANDLED;135135+}136136+137137+void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *channel)138138+{139139+ int notify;140140+141141+ channel->u.req.ring.req_prod_pvt++;142142+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&channel->u.req.ring, notify);143143+ if (notify)144144+ notify_remote_via_irq(channel->irq);145145+}146146+147147+static void evtchnl_free(struct xen_snd_front_info *front_info,148148+ struct xen_snd_front_evtchnl *channel)149149+{150150+ unsigned long page = 0;151151+152152+ if (channel->type == EVTCHNL_TYPE_REQ)153153+ page = (unsigned long)channel->u.req.ring.sring;154154+ else if (channel->type == EVTCHNL_TYPE_EVT)155155+ page = (unsigned long)channel->u.evt.page;156156+157157+ if (!page)158158+ return;159159+160160+ channel->state = EVTCHNL_STATE_DISCONNECTED;161161+ if (channel->type == EVTCHNL_TYPE_REQ) {162162+ /* Release all who still waits for response if any. */163163+ channel->u.req.resp_status = -EIO;164164+ complete_all(&channel->u.req.completion);165165+ }166166+167167+ if (channel->irq)168168+ unbind_from_irqhandler(channel->irq, channel);169169+170170+ if (channel->port)171171+ xenbus_free_evtchn(front_info->xb_dev, channel->port);172172+173173+ /* End access and free the page. */174174+ if (channel->gref != GRANT_INVALID_REF)175175+ gnttab_end_foreign_access(channel->gref, 0, page);176176+ else177177+ free_page(page);178178+179179+ memset(channel, 0, sizeof(*channel));180180+}181181+182182+void xen_snd_front_evtchnl_free_all(struct xen_snd_front_info *front_info)183183+{184184+ int i;185185+186186+ if (!front_info->evt_pairs)187187+ return;188188+189189+ for (i = 0; i < front_info->num_evt_pairs; i++) {190190+ evtchnl_free(front_info, &front_info->evt_pairs[i].req);191191+ evtchnl_free(front_info, &front_info->evt_pairs[i].evt);192192+ }193193+194194+ kfree(front_info->evt_pairs);195195+ front_info->evt_pairs = NULL;196196+}197197+198198+static int evtchnl_alloc(struct xen_snd_front_info *front_info, int index,199199+ struct xen_snd_front_evtchnl *channel,200200+ enum xen_snd_front_evtchnl_type type)201201+{202202+ struct xenbus_device *xb_dev = front_info->xb_dev;203203+ unsigned long page;204204+ grant_ref_t gref;205205+ irq_handler_t handler;206206+ char *handler_name = NULL;207207+ int ret;208208+209209+ memset(channel, 0, sizeof(*channel));210210+ channel->type = type;211211+ channel->index = index;212212+ channel->front_info = front_info;213213+ channel->state = EVTCHNL_STATE_DISCONNECTED;214214+ channel->gref = GRANT_INVALID_REF;215215+ page = get_zeroed_page(GFP_KERNEL);216216+ if (!page) {217217+ ret = -ENOMEM;218218+ goto fail;219219+ }220220+221221+ handler_name = kasprintf(GFP_KERNEL, "%s-%s", XENSND_DRIVER_NAME,222222+ type == EVTCHNL_TYPE_REQ ?223223+ XENSND_FIELD_RING_REF :224224+ XENSND_FIELD_EVT_RING_REF);225225+ if (!handler_name) {226226+ ret = -ENOMEM;227227+ goto fail;228228+ }229229+230230+ mutex_init(&channel->ring_io_lock);231231+232232+ if (type == EVTCHNL_TYPE_REQ) {233233+ struct xen_sndif_sring *sring = (struct xen_sndif_sring *)page;234234+235235+ init_completion(&channel->u.req.completion);236236+ mutex_init(&channel->u.req.req_io_lock);237237+ SHARED_RING_INIT(sring);238238+ FRONT_RING_INIT(&channel->u.req.ring, sring, XEN_PAGE_SIZE);239239+240240+ ret = xenbus_grant_ring(xb_dev, sring, 1, &gref);241241+ if (ret < 0) {242242+ channel->u.req.ring.sring = NULL;243243+ goto fail;244244+ }245245+246246+ handler = evtchnl_interrupt_req;247247+ } else {248248+ ret = gnttab_grant_foreign_access(xb_dev->otherend_id,249249+ virt_to_gfn((void *)page), 0);250250+ if (ret < 0)251251+ goto fail;252252+253253+ channel->u.evt.page = (struct xensnd_event_page *)page;254254+ gref = ret;255255+ handler = evtchnl_interrupt_evt;256256+ }257257+258258+ channel->gref = gref;259259+260260+ ret = xenbus_alloc_evtchn(xb_dev, &channel->port);261261+ if (ret < 0)262262+ goto fail;263263+264264+ ret = bind_evtchn_to_irq(channel->port);265265+ if (ret < 0) {266266+ dev_err(&xb_dev->dev,267267+ "Failed to bind IRQ for domid %d port %d: %d\n",268268+ front_info->xb_dev->otherend_id, channel->port, ret);269269+ goto fail;270270+ }271271+272272+ channel->irq = ret;273273+274274+ ret = request_threaded_irq(channel->irq, NULL, handler,275275+ IRQF_ONESHOT, handler_name, channel);276276+ if (ret < 0) {277277+ dev_err(&xb_dev->dev, "Failed to request IRQ %d: %d\n",278278+ channel->irq, ret);279279+ goto fail;280280+ }281281+282282+ kfree(handler_name);283283+ return 0;284284+285285+fail:286286+ if (page)287287+ free_page(page);288288+ kfree(handler_name);289289+ dev_err(&xb_dev->dev, "Failed to allocate ring: %d\n", ret);290290+ return ret;291291+}292292+293293+int xen_snd_front_evtchnl_create_all(struct xen_snd_front_info *front_info,294294+ int num_streams)295295+{296296+ struct xen_front_cfg_card *cfg = &front_info->cfg;297297+ struct device *dev = &front_info->xb_dev->dev;298298+ int d, ret = 0;299299+300300+ front_info->evt_pairs =301301+ kcalloc(num_streams,302302+ sizeof(struct xen_snd_front_evtchnl_pair),303303+ GFP_KERNEL);304304+ if (!front_info->evt_pairs)305305+ return -ENOMEM;306306+307307+ /* Iterate over devices and their streams and create event channels. */308308+ for (d = 0; d < cfg->num_pcm_instances; d++) {309309+ struct xen_front_cfg_pcm_instance *pcm_instance;310310+ int s, index;311311+312312+ pcm_instance = &cfg->pcm_instances[d];313313+314314+ for (s = 0; s < pcm_instance->num_streams_pb; s++) {315315+ index = pcm_instance->streams_pb[s].index;316316+317317+ ret = evtchnl_alloc(front_info, index,318318+ &front_info->evt_pairs[index].req,319319+ EVTCHNL_TYPE_REQ);320320+ if (ret < 0) {321321+ dev_err(dev, "Error allocating control channel\n");322322+ goto fail;323323+ }324324+325325+ ret = evtchnl_alloc(front_info, index,326326+ &front_info->evt_pairs[index].evt,327327+ EVTCHNL_TYPE_EVT);328328+ if (ret < 0) {329329+ dev_err(dev, "Error allocating in-event channel\n");330330+ goto fail;331331+ }332332+ }333333+334334+ for (s = 0; s < pcm_instance->num_streams_cap; s++) {335335+ index = pcm_instance->streams_cap[s].index;336336+337337+ ret = evtchnl_alloc(front_info, index,338338+ &front_info->evt_pairs[index].req,339339+ EVTCHNL_TYPE_REQ);340340+ if (ret < 0) {341341+ dev_err(dev, "Error allocating control channel\n");342342+ goto fail;343343+ }344344+345345+ ret = evtchnl_alloc(front_info, index,346346+ &front_info->evt_pairs[index].evt,347347+ EVTCHNL_TYPE_EVT);348348+ if (ret < 0) {349349+ dev_err(dev, "Error allocating in-event channel\n");350350+ goto fail;351351+ }352352+ }353353+ }354354+355355+ front_info->num_evt_pairs = num_streams;356356+ return 0;357357+358358+fail:359359+ xen_snd_front_evtchnl_free_all(front_info);360360+ return ret;361361+}362362+363363+static int evtchnl_publish(struct xenbus_transaction xbt,364364+ struct xen_snd_front_evtchnl *channel,365365+ const char *path, const char *node_ring,366366+ const char *node_chnl)367367+{368368+ struct xenbus_device *xb_dev = channel->front_info->xb_dev;369369+ int ret;370370+371371+ /* Write control channel ring reference. */372372+ ret = xenbus_printf(xbt, path, node_ring, "%u", channel->gref);373373+ if (ret < 0) {374374+ dev_err(&xb_dev->dev, "Error writing ring-ref: %d\n", ret);375375+ return ret;376376+ }377377+378378+ /* Write event channel ring reference. */379379+ ret = xenbus_printf(xbt, path, node_chnl, "%u", channel->port);380380+ if (ret < 0) {381381+ dev_err(&xb_dev->dev, "Error writing event channel: %d\n", ret);382382+ return ret;383383+ }384384+385385+ return 0;386386+}387387+388388+int xen_snd_front_evtchnl_publish_all(struct xen_snd_front_info *front_info)389389+{390390+ struct xen_front_cfg_card *cfg = &front_info->cfg;391391+ struct xenbus_transaction xbt;392392+ int ret, d;393393+394394+again:395395+ ret = xenbus_transaction_start(&xbt);396396+ if (ret < 0) {397397+ xenbus_dev_fatal(front_info->xb_dev, ret,398398+ "starting transaction");399399+ return ret;400400+ }401401+402402+ for (d = 0; d < cfg->num_pcm_instances; d++) {403403+ struct xen_front_cfg_pcm_instance *pcm_instance;404404+ int s, index;405405+406406+ pcm_instance = &cfg->pcm_instances[d];407407+408408+ for (s = 0; s < pcm_instance->num_streams_pb; s++) {409409+ index = pcm_instance->streams_pb[s].index;410410+411411+ ret = evtchnl_publish(xbt,412412+ &front_info->evt_pairs[index].req,413413+ pcm_instance->streams_pb[s].xenstore_path,414414+ XENSND_FIELD_RING_REF,415415+ XENSND_FIELD_EVT_CHNL);416416+ if (ret < 0)417417+ goto fail;418418+419419+ ret = evtchnl_publish(xbt,420420+ &front_info->evt_pairs[index].evt,421421+ pcm_instance->streams_pb[s].xenstore_path,422422+ XENSND_FIELD_EVT_RING_REF,423423+ XENSND_FIELD_EVT_EVT_CHNL);424424+ if (ret < 0)425425+ goto fail;426426+ }427427+428428+ for (s = 0; s < pcm_instance->num_streams_cap; s++) {429429+ index = pcm_instance->streams_cap[s].index;430430+431431+ ret = evtchnl_publish(xbt,432432+ &front_info->evt_pairs[index].req,433433+ pcm_instance->streams_cap[s].xenstore_path,434434+ XENSND_FIELD_RING_REF,435435+ XENSND_FIELD_EVT_CHNL);436436+ if (ret < 0)437437+ goto fail;438438+439439+ ret = evtchnl_publish(xbt,440440+ &front_info->evt_pairs[index].evt,441441+ pcm_instance->streams_cap[s].xenstore_path,442442+ XENSND_FIELD_EVT_RING_REF,443443+ XENSND_FIELD_EVT_EVT_CHNL);444444+ if (ret < 0)445445+ goto fail;446446+ }447447+ }448448+ ret = xenbus_transaction_end(xbt, 0);449449+ if (ret < 0) {450450+ if (ret == -EAGAIN)451451+ goto again;452452+453453+ xenbus_dev_fatal(front_info->xb_dev, ret,454454+ "completing transaction");455455+ goto fail_to_end;456456+ }457457+ return 0;458458+fail:459459+ xenbus_transaction_end(xbt, 1);460460+fail_to_end:461461+ xenbus_dev_fatal(front_info->xb_dev, ret, "writing XenStore");462462+ return ret;463463+}464464+465465+void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair,466466+ bool is_connected)467467+{468468+ enum xen_snd_front_evtchnl_state state;469469+470470+ if (is_connected)471471+ state = EVTCHNL_STATE_CONNECTED;472472+ else473473+ state = EVTCHNL_STATE_DISCONNECTED;474474+475475+ mutex_lock(&evt_pair->req.ring_io_lock);476476+ evt_pair->req.state = state;477477+ mutex_unlock(&evt_pair->req.ring_io_lock);478478+479479+ mutex_lock(&evt_pair->evt.ring_io_lock);480480+ evt_pair->evt.state = state;481481+ mutex_unlock(&evt_pair->evt.ring_io_lock);482482+}483483+484484+void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pair)485485+{486486+ mutex_lock(&evt_pair->req.ring_io_lock);487487+ evt_pair->req.evt_next_id = 0;488488+ mutex_unlock(&evt_pair->req.ring_io_lock);489489+490490+ mutex_lock(&evt_pair->evt.ring_io_lock);491491+ evt_pair->evt.evt_next_id = 0;492492+ mutex_unlock(&evt_pair->evt.ring_io_lock);493493+}494494+
+95
sound/xen/xen_snd_front_evtchnl.h
···11+/* SPDX-License-Identifier: GPL-2.0 OR MIT */22+33+/*44+ * Xen para-virtual sound device55+ *66+ * Copyright (C) 2016-2018 EPAM Systems Inc.77+ *88+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>99+ */1010+1111+#ifndef __XEN_SND_FRONT_EVTCHNL_H1212+#define __XEN_SND_FRONT_EVTCHNL_H1313+1414+#include <xen/interface/io/sndif.h>1515+1616+struct xen_snd_front_info;1717+1818+#ifndef GRANT_INVALID_REF1919+/*2020+ * FIXME: usage of grant reference 0 as invalid grant reference:2121+ * grant reference 0 is valid, but never exposed to a PV driver,2222+ * because of the fact it is already in use/reserved by the PV console.2323+ */2424+#define GRANT_INVALID_REF 02525+#endif2626+2727+/* Timeout in ms to wait for backend to respond. */2828+#define VSND_WAIT_BACK_MS 30002929+3030+enum xen_snd_front_evtchnl_state {3131+ EVTCHNL_STATE_DISCONNECTED,3232+ EVTCHNL_STATE_CONNECTED,3333+};3434+3535+enum xen_snd_front_evtchnl_type {3636+ EVTCHNL_TYPE_REQ,3737+ EVTCHNL_TYPE_EVT,3838+};3939+4040+struct xen_snd_front_evtchnl {4141+ struct xen_snd_front_info *front_info;4242+ int gref;4343+ int port;4444+ int irq;4545+ int index;4646+ /* State of the event channel. */4747+ enum xen_snd_front_evtchnl_state state;4848+ enum xen_snd_front_evtchnl_type type;4949+ /* Either response id or incoming event id. */5050+ u16 evt_id;5151+ /* Next request id or next expected event id. */5252+ u16 evt_next_id;5353+ /* Shared ring access lock. */5454+ struct mutex ring_io_lock;5555+ union {5656+ struct {5757+ struct xen_sndif_front_ring ring;5858+ struct completion completion;5959+ /* Serializer for backend IO: request/response. */6060+ struct mutex req_io_lock;6161+6262+ /* Latest response status. */6363+ int resp_status;6464+ union {6565+ struct xensnd_query_hw_param hw_param;6666+ } resp;6767+ } req;6868+ struct {6969+ struct xensnd_event_page *page;7070+ /* This is needed to handle XENSND_EVT_CUR_POS event. */7171+ struct snd_pcm_substream *substream;7272+ } evt;7373+ } u;7474+};7575+7676+struct xen_snd_front_evtchnl_pair {7777+ struct xen_snd_front_evtchnl req;7878+ struct xen_snd_front_evtchnl evt;7979+};8080+8181+int xen_snd_front_evtchnl_create_all(struct xen_snd_front_info *front_info,8282+ int num_streams);8383+8484+void xen_snd_front_evtchnl_free_all(struct xen_snd_front_info *front_info);8585+8686+int xen_snd_front_evtchnl_publish_all(struct xen_snd_front_info *front_info);8787+8888+void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *evtchnl);8989+9090+void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair,9191+ bool is_connected);9292+9393+void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pair);9494+9595+#endif /* __XEN_SND_FRONT_EVTCHNL_H */
+194
sound/xen/xen_snd_front_shbuf.c
···11+// SPDX-License-Identifier: GPL-2.0 OR MIT22+33+/*44+ * Xen para-virtual sound device55+ *66+ * Copyright (C) 2016-2018 EPAM Systems Inc.77+ *88+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>99+ */1010+1111+#include <linux/kernel.h>1212+#include <xen/xen.h>1313+#include <xen/xenbus.h>1414+1515+#include "xen_snd_front_shbuf.h"1616+1717+grant_ref_t xen_snd_front_shbuf_get_dir_start(struct xen_snd_front_shbuf *buf)1818+{1919+ if (!buf->grefs)2020+ return GRANT_INVALID_REF;2121+2222+ return buf->grefs[0];2323+}2424+2525+void xen_snd_front_shbuf_clear(struct xen_snd_front_shbuf *buf)2626+{2727+ memset(buf, 0, sizeof(*buf));2828+}2929+3030+void xen_snd_front_shbuf_free(struct xen_snd_front_shbuf *buf)3131+{3232+ int i;3333+3434+ if (buf->grefs) {3535+ for (i = 0; i < buf->num_grefs; i++)3636+ if (buf->grefs[i] != GRANT_INVALID_REF)3737+ gnttab_end_foreign_access(buf->grefs[i],3838+ 0, 0UL);3939+ kfree(buf->grefs);4040+ }4141+ kfree(buf->directory);4242+ free_pages_exact(buf->buffer, buf->buffer_sz);4343+ xen_snd_front_shbuf_clear(buf);4444+}4545+4646+/*4747+ * number of grant references a page can hold with respect to the4848+ * xensnd_page_directory header4949+ */5050+#define XENSND_NUM_GREFS_PER_PAGE ((XEN_PAGE_SIZE - \5151+ offsetof(struct xensnd_page_directory, gref)) / \5252+ sizeof(grant_ref_t))5353+5454+static void fill_page_dir(struct xen_snd_front_shbuf *buf,5555+ int num_pages_dir)5656+{5757+ struct xensnd_page_directory *page_dir;5858+ unsigned char *ptr;5959+ int i, cur_gref, grefs_left, to_copy;6060+6161+ ptr = buf->directory;6262+ grefs_left = buf->num_grefs - num_pages_dir;6363+ /*6464+ * skip grant references at the beginning, they are for pages granted6565+ * for the page directory itself6666+ */6767+ cur_gref = num_pages_dir;6868+ for (i = 0; i < num_pages_dir; i++) {6969+ page_dir = (struct xensnd_page_directory *)ptr;7070+ if (grefs_left <= XENSND_NUM_GREFS_PER_PAGE) {7171+ to_copy = grefs_left;7272+ page_dir->gref_dir_next_page = GRANT_INVALID_REF;7373+ } else {7474+ to_copy = XENSND_NUM_GREFS_PER_PAGE;7575+ page_dir->gref_dir_next_page = buf->grefs[i + 1];7676+ }7777+7878+ memcpy(&page_dir->gref, &buf->grefs[cur_gref],7979+ to_copy * sizeof(grant_ref_t));8080+8181+ ptr += XEN_PAGE_SIZE;8282+ grefs_left -= to_copy;8383+ cur_gref += to_copy;8484+ }8585+}8686+8787+static int grant_references(struct xenbus_device *xb_dev,8888+ struct xen_snd_front_shbuf *buf,8989+ int num_pages_dir, int num_pages_buffer,9090+ int num_grefs)9191+{9292+ grant_ref_t priv_gref_head;9393+ unsigned long frame;9494+ int ret, i, j, cur_ref;9595+ int otherend_id;9696+9797+ ret = gnttab_alloc_grant_references(num_grefs, &priv_gref_head);9898+ if (ret)9999+ return ret;100100+101101+ buf->num_grefs = num_grefs;102102+ otherend_id = xb_dev->otherend_id;103103+ j = 0;104104+105105+ for (i = 0; i < num_pages_dir; i++) {106106+ cur_ref = gnttab_claim_grant_reference(&priv_gref_head);107107+ if (cur_ref < 0) {108108+ ret = cur_ref;109109+ goto fail;110110+ }111111+112112+ frame = xen_page_to_gfn(virt_to_page(buf->directory +113113+ XEN_PAGE_SIZE * i));114114+ gnttab_grant_foreign_access_ref(cur_ref, otherend_id, frame, 0);115115+ buf->grefs[j++] = cur_ref;116116+ }117117+118118+ for (i = 0; i < num_pages_buffer; i++) {119119+ cur_ref = gnttab_claim_grant_reference(&priv_gref_head);120120+ if (cur_ref < 0) {121121+ ret = cur_ref;122122+ goto fail;123123+ }124124+125125+ frame = xen_page_to_gfn(virt_to_page(buf->buffer +126126+ XEN_PAGE_SIZE * i));127127+ gnttab_grant_foreign_access_ref(cur_ref, otherend_id, frame, 0);128128+ buf->grefs[j++] = cur_ref;129129+ }130130+131131+ gnttab_free_grant_references(priv_gref_head);132132+ fill_page_dir(buf, num_pages_dir);133133+ return 0;134134+135135+fail:136136+ gnttab_free_grant_references(priv_gref_head);137137+ return ret;138138+}139139+140140+static int alloc_int_buffers(struct xen_snd_front_shbuf *buf,141141+ int num_pages_dir, int num_pages_buffer,142142+ int num_grefs)143143+{144144+ buf->grefs = kcalloc(num_grefs, sizeof(*buf->grefs), GFP_KERNEL);145145+ if (!buf->grefs)146146+ return -ENOMEM;147147+148148+ buf->directory = kcalloc(num_pages_dir, XEN_PAGE_SIZE, GFP_KERNEL);149149+ if (!buf->directory)150150+ goto fail;151151+152152+ buf->buffer_sz = num_pages_buffer * XEN_PAGE_SIZE;153153+ buf->buffer = alloc_pages_exact(buf->buffer_sz, GFP_KERNEL);154154+ if (!buf->buffer)155155+ goto fail;156156+157157+ return 0;158158+159159+fail:160160+ kfree(buf->grefs);161161+ buf->grefs = NULL;162162+ kfree(buf->directory);163163+ buf->directory = NULL;164164+ return -ENOMEM;165165+}166166+167167+int xen_snd_front_shbuf_alloc(struct xenbus_device *xb_dev,168168+ struct xen_snd_front_shbuf *buf,169169+ unsigned int buffer_sz)170170+{171171+ int num_pages_buffer, num_pages_dir, num_grefs;172172+ int ret;173173+174174+ xen_snd_front_shbuf_clear(buf);175175+176176+ num_pages_buffer = DIV_ROUND_UP(buffer_sz, XEN_PAGE_SIZE);177177+ /* number of pages the page directory consumes itself */178178+ num_pages_dir = DIV_ROUND_UP(num_pages_buffer,179179+ XENSND_NUM_GREFS_PER_PAGE);180180+ num_grefs = num_pages_buffer + num_pages_dir;181181+182182+ ret = alloc_int_buffers(buf, num_pages_dir,183183+ num_pages_buffer, num_grefs);184184+ if (ret < 0)185185+ return ret;186186+187187+ ret = grant_references(xb_dev, buf, num_pages_dir, num_pages_buffer,188188+ num_grefs);189189+ if (ret < 0)190190+ return ret;191191+192192+ fill_page_dir(buf, num_pages_dir);193193+ return 0;194194+}