/* This function routes the sound from a virtual channel to a real output */ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, int gain) { int index; if (snd_BUG_ON(pipe >= num_pipes_out(chip) || output >= num_busses_out(chip))) return -EINVAL; if (wait_handshake(chip)) return -EIO; chip->vmixer_gain[output][pipe] = gain; index = output * num_pipes_out(chip) + pipe; chip->comm_page->vmixer[index] = gain; DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); return 0; }
static int ca_midi_input_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->interrupt_disable(midi,midi->rx_enable); midi->midi_mode &= ~CA_MIDI_MODE_INPUT; midi->substream_input = NULL; if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 0); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }
static ssize_t snd_compr_write(struct file *f, const char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { mutex_unlock(&stream->device->lock); return -EBADFD; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %zu\n", avail); if (avail > count) avail = count; if (stream->ops->copy) { char __user* cbuf = (char __user*)buf; retval = stream->ops->copy(stream, cbuf, avail); } else { retval = snd_compr_write_data(stream, buf, avail); } if (retval > 0) stream->runtime->total_bytes_available += retval; if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) { stream->runtime->state = SNDRV_PCM_STATE_PREPARED; pr_debug("stream prepared, Houston we are good to go\n"); } mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_write(struct file *f, const char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); /* write is allowed when stream is running or has been steup */ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { mutex_unlock(&stream->device->lock); return -EBADFD; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %ld\n", (unsigned long)avail); /* calculate how much we can write to buffer */ if (avail > count) avail = count; if (stream->ops->copy) retval = stream->ops->copy(stream, buf, avail); else retval = snd_compr_write_data(stream, buf, avail); if (retval > 0) stream->runtime->total_bytes_available += retval; /* while initiating the stream, write should be called before START * call, so in setup move state */ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) { stream->runtime->state = SNDRV_PCM_STATE_PREPARED; pr_debug("stream prepared, Houston we are good to go\n"); } mutex_unlock(&stream->device->lock); return retval; }
static int ca_midi_output_open(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= CA_MIDI_MODE_OUTPUT; midi->substream_output = substream; if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 1); ca_midi_cmd(midi, midi->enter_uart, 1); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }
int snd_seq_pool_done(struct snd_seq_pool *pool) { unsigned long flags; struct snd_seq_event_cell *ptr; int max_count = 5 * HZ; if (snd_BUG_ON(!pool)) return -EINVAL; spin_lock_irqsave(&pool->lock, flags); pool->closing = 1; spin_unlock_irqrestore(&pool->lock, flags); if (waitqueue_active(&pool->output_sleep)) wake_up(&pool->output_sleep); while (atomic_read(&pool->counter) > 0) { if (max_count == 0) { snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter)); break; } schedule_timeout_uninterruptible(1); max_count--; } spin_lock_irqsave(&pool->lock, flags); ptr = pool->ptr; pool->ptr = NULL; pool->free = NULL; pool->total_elements = 0; spin_unlock_irqrestore(&pool->lock, flags); vfree(ptr); spin_lock_irqsave(&pool->lock, flags); pool->closing = 0; spin_unlock_irqrestore(&pool->lock, flags); return 0; }
static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count) { struct snd_opl3 *opl3; struct sbi_instrument sbi; char name[32]; int err, type; if (snd_BUG_ON(!arg)) return -ENXIO; opl3 = arg->private_data; if (format == FM_PATCH) type = FM_PATCH_OPL2; else if (format == OPL3_PATCH) type = FM_PATCH_OPL3; else return -EINVAL; if (count < (int)sizeof(sbi)) { snd_printk(KERN_ERR "FM Error: Patch record too short\n"); return -EINVAL; } if (copy_from_user(&sbi, buf, sizeof(sbi))) return -EFAULT; if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", sbi.channel); return -EINVAL; } memset(name, 0, sizeof(name)); sprintf(name, "Chan%d", sbi.channel); err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL, sbi.operators); if (err < 0) return err; return sizeof(sbi); }
void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) { int i; struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) return; for (i = 0; i < dp->max_synthdev; i++) { info = &dp->synths[i]; if (! info->opened) continue; if (info->is_midi) { if (midi_synth_dev.opened > 0) { snd_seq_oss_midi_close(dp, info->midi_mapped); midi_synth_dev.opened--; } } else { rec = get_sdev(i); if (rec == NULL) continue; if (rec->opened > 0) { #ifdef CONFIG_DEBUG_PRINTK debug_printk(("synth %d closed\n", i)); #else debug_; #endif rec->oper.close(&info->arg); module_put(rec->oper.owner); rec->opened = 0; } snd_use_lock_free(&rec->use_lock); } kfree(info->sysex); info->sysex = NULL; kfree(info->ch); info->ch = NULL; } dp->synth_opened = 0; dp->max_synthdev = 0; }
/* * prepare playback/capture channel */ static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream) { struct nm256 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; if (snd_BUG_ON(!s)) return -ENXIO; s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size); s->period_size = frames_to_bytes(runtime, substream->runtime->period_size); s->periods = substream->runtime->periods; s->cur_period = 0; spin_lock_irq(&chip->reg_lock); s->running = 0; snd_nm256_set_format(chip, s, substream); spin_unlock_irq(&chip->reg_lock); return 0; }
static int snd_hwdep_dev_disconnect(struct snd_device *device) { struct snd_hwdep *hwdep = device->device_data; if (snd_BUG_ON(!hwdep)) return -ENXIO; mutex_lock(®ister_mutex); if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) { mutex_unlock(®ister_mutex); return -EINVAL; } #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); mutex_unlock(®ister_mutex); return 0; }
/* Send a buffer full of MIDI data to the DSP Returns how many actually written or < 0 on error */ static int write_midi(struct echoaudio *chip, u8 *data, int bytes) { if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE)) return -EINVAL; if (wait_handshake(chip)) return -EIO; /* HF4 indicates that it is safe to write MIDI output data */ if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4)) return 0; chip->comm_page->midi_output[0] = bytes; memcpy(&chip->comm_page->midi_output[1], data, bytes); chip->comm_page->midi_out_free_count = 0; clear_handshake(chip); send_vector(chip, DSP_VC_MIDI_WRITE); DE_MID(("write_midi: %d\n", bytes)); return bytes; }
static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int changed = 0; int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; int* stored_volume; int i; mutex_lock(&chip->mgr->mixer_mutex); if (is_capture) { if (is_aes) /* AES capture */ stored_volume = chip->digital_capture_volume[1]; else /* analog capture */ stored_volume = chip->digital_capture_volume[0]; } else { snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); if (is_aes) /* AES playback */ stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; else /* analog playback */ stored_volume = chip->digital_playback_volume[idx]; } for (i = 0; i < 2; i++) { int vol = ucontrol->value.integer.value[i]; if (vol < MIXART_DIGITAL_LEVEL_MIN || vol > MIXART_DIGITAL_LEVEL_MAX) continue; if (stored_volume[i] != vol) { stored_volume[i] = vol; changed = 1; } } if (changed) { if (is_capture) mixart_update_capture_stream_level(chip, is_aes); else mixart_update_playback_stream_level(chip, is_aes, idx); } mutex_unlock(&chip->mgr->mixer_mutex); return changed; }
/** * snd_pcm_lib_malloc_pages - allocate the DMA buffer * @substream: the substream to allocate the DMA buffer to * @size: the requested buffer size in bytes * * Allocates the DMA buffer on the BUS type given earlier to * snd_pcm_lib_preallocate_xxx_pages(). * * Return: 1 if the buffer is changed, 0 if not changed, or a negative * code on failure. */ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) { struct snd_pcm_runtime *runtime; struct snd_dma_buffer *dmab = NULL; if (PCM_RUNTIME_CHECK(substream)) return -EINVAL; if (snd_BUG_ON(substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_UNKNOWN)) return -EINVAL; runtime = substream->runtime; if (runtime->dma_buffer_p) { /* perphaps, we might free the large DMA memory region to save some space here, but the actual solution costs us less time */ if (runtime->dma_buffer_p->bytes >= size) { runtime->dma_bytes = size; return 0; /* ok, do not change */ } snd_pcm_lib_free_pages(substream); } if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { dmab = &substream->dma_buffer; /* use the pre-allocated buffer */ } else { dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); if (! dmab) return -ENOMEM; dmab->dev = substream->dma_buffer.dev; if (snd_dma_alloc_pages(substream->dma_buffer.dev.type, substream->dma_buffer.dev.dev, size, dmab) < 0) { kfree(dmab); return -ENOMEM; } } snd_pcm_set_runtime_buffer(substream, dmab); runtime->dma_bytes = size; return 1; /* area was changed */ }
static int snd_timer_user_status_compat(struct file *file, struct snd_timer_status32 __user *_status) { struct snd_timer_user *tu; struct snd_timer_status status; tu = file->private_data; if (snd_BUG_ON(!tu->timeri)) return -ENXIO; memset(&status, 0, sizeof(status)); status.tstamp = tu->tstamp; status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.overrun = tu->overrun; spin_lock_irq(&tu->qlock); status.queue = tu->qused; spin_unlock_irq(&tu->qlock); if (copy_to_user(_status, &status, sizeof(status))) return -EFAULT; return 0; }
static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int *stored_volume; int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; mutex_lock(&chip->mgr->mixer_mutex); if(is_capture) { if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ } else { snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); if(is_aes) stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */ else stored_volume = chip->digital_playback_volume[idx]; /* analog playback */ } ucontrol->value.integer.value[0] = stored_volume[0]; ucontrol->value.integer.value[1] = stored_volume[1]; mutex_unlock(&chip->mgr->mixer_mutex); return 0; }
snd_pcm_sframes_t ksnd_pcm_mmap_commit(ksnd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames) { snd_pcm_substream_t *substream = pcm->substream; snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_uframes_t appl_ptr; snd_pcm_sframes_t res = frames; int err; if (snd_BUG_ON(!substream)) return -EFAULT; /* for SPDIF we need to run though the just committed PCM samples and * add formating (unless raw mode is enabled) */ // BUG_ON(substream->pcm->card->number == 2); /* TODO: magic number */ snd_pcm_stream_lock_irq(substream); switch (_ksnd_pcm_state(substream)) { case SNDRV_PCM_STATE_XRUN: res = -EPIPE; goto _end_unlock; case SNDRV_PCM_STATE_SUSPENDED: res = -ESTRPIPE; goto _end_unlock; } appl_ptr = runtime->control->appl_ptr; /* verify no-one is interleaving access to the playback */ // TODO: what about capture? BUG_ON(substream->stream == SNDRV_PCM_STREAM_PLAYBACK && (appl_ptr % runtime->buffer_size) != offset); appl_ptr += frames; if (appl_ptr >= runtime->boundary) appl_ptr = 0; err = _ksnd_pcm_update_appl_ptr(substream, appl_ptr); if (err < 0) res = err; _end_unlock: snd_pcm_stream_unlock_irq(substream); return res; }
/* common trigger callback * calling the lowlevel callbacks in it */ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct atiixp *chip = snd_pcm_substream_chip(substream); struct atiixp_dma *dma = substream->runtime->private_data; int err = 0; if (snd_BUG_ON(!dma->ops->enable_transfer || !dma->ops->flush_dma)) return -EINVAL; spin_lock(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: dma->ops->enable_transfer(chip, 1); dma->running = 1; dma->suspended = 0; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: dma->ops->enable_transfer(chip, 0); dma->running = 0; dma->suspended = cmd == SNDRV_PCM_TRIGGER_SUSPEND; break; default: err = -EINVAL; break; } if (! err) { snd_atiixp_check_bus_busy(chip); if (cmd == SNDRV_PCM_TRIGGER_STOP) { dma->ops->flush_dma(chip); snd_atiixp_check_bus_busy(chip); } } spin_unlock(&chip->reg_lock); return err; }
/* open OSS sequencer */ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) { struct snd_opl3 *opl3 = closure; int err; if (snd_BUG_ON(!arg)) return -ENXIO; if ((err = snd_opl3_synth_setup(opl3)) < 0) return err; /* fill the argument data */ arg->private_data = opl3; arg->addr.client = opl3->oss_chset->client; arg->addr.port = opl3->oss_chset->port; if ((err = snd_opl3_synth_use_inc(opl3)) < 0) return err; opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH; return 0; }
static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_emu10k1 *emu; struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; unsigned long flags; int err = 0; emu = midi->emu; if (snd_BUG_ON(!emu)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); snd_emu10k1_intr_disable(emu, midi->tx_enable); midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; midi->substream_output = NULL; if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return err; }
/* change the size of pool; all old events are removed */ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) { unsigned long flags; struct snd_seq_pool *newpool, *oldpool; struct snd_seq_event_cell *cell, *next, *oldhead; if (snd_BUG_ON(!f || !f->pool)) return -EINVAL; /* allocate new pool */ newpool = snd_seq_pool_new(poolsize); if (newpool == NULL) return -ENOMEM; if (snd_seq_pool_init(newpool) < 0) { snd_seq_pool_delete(&newpool); return -ENOMEM; } spin_lock_irqsave(&f->lock, flags); /* remember old pool */ oldpool = f->pool; oldhead = f->head; /* exchange pools */ f->pool = newpool; f->head = NULL; f->tail = NULL; f->cells = 0; /* NOTE: overflow flag is not cleared */ spin_unlock_irqrestore(&f->lock, flags); /* release cells in old pool */ for (cell = oldhead; cell; cell = next) { next = cell->next; snd_seq_cell_free(cell); } snd_seq_pool_delete(&oldpool); return 0; }
int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate) { struct cs8427 *chip; char *status; int err, reset; if (snd_BUG_ON(!cs8427)) return -ENXIO; chip = cs8427->private_data; status = chip->playback.pcm_status; snd_i2c_lock(cs8427->bus); if (status[0] & IEC958_AES0_PROFESSIONAL) { status[0] &= ~IEC958_AES0_PRO_FS; switch (rate) { case 32000: status[0] |= IEC958_AES0_PRO_FS_32000; break; case 44100: status[0] |= IEC958_AES0_PRO_FS_44100; break; case 48000: status[0] |= IEC958_AES0_PRO_FS_48000; break; default: status[0] |= IEC958_AES0_PRO_FS_NOTID; break; } } else { status[3] &= ~IEC958_AES3_CON_FS; switch (rate) { case 32000: status[3] |= IEC958_AES3_CON_FS_32000; break; case 44100: status[3] |= IEC958_AES3_CON_FS_44100; break; case 48000: status[3] |= IEC958_AES3_CON_FS_48000; break; } } err = snd_cs8427_send_corudata(cs8427, 0, status, 24); if (err > 0) snd_ctl_notify(cs8427->bus->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->playback.pcm_ctl->id); reset = chip->rate != rate; chip->rate = rate; snd_i2c_unlock(cs8427->bus); if (reset) snd_cs8427_reset(cs8427); return err < 0 ? err : 0; }
/* * Reset the chip using run bit, also lock PLL using ILRCK and * put back AES3INPUT. This workaround is described in latest * CS8427 datasheet, otherwise TXDSERIAL will not work. */ static void snd_cs8427_reset(struct snd_i2c_device *cs8427) { struct cs8427 *chip; unsigned long end_time; int data, aes3input = 0; if (snd_BUG_ON(!cs8427)) return; chip = cs8427->private_data; snd_i2c_lock(cs8427->bus); if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) == CS8427_RXDAES3INPUT) /* AES3 bit is set */ aes3input = 1; chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK); snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]); udelay(200); chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RUN | CS8427_RXDILRCK; snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]); udelay(200); snd_i2c_unlock(cs8427->bus); end_time = jiffies + chip->reset_timeout; while (time_after_eq(end_time, jiffies)) { snd_i2c_lock(cs8427->bus); data = snd_cs8427_reg_read(cs8427, CS8427_REG_RECVERRORS); snd_i2c_unlock(cs8427->bus); if (!(data & CS8427_UNLOCK)) break; schedule_timeout_uninterruptible(1); } snd_i2c_lock(cs8427->bus); chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~CS8427_RXDMASK; if (aes3input) chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RXDAES3INPUT; snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]); snd_i2c_unlock(cs8427->bus); }
/* allocate room specified number of events */ int snd_seq_pool_init(struct snd_seq_pool *pool) { int cell; struct snd_seq_event_cell *cellptr; unsigned long flags; if (snd_BUG_ON(!pool)) return -EINVAL; cellptr = vmalloc(array_size(sizeof(struct snd_seq_event_cell), pool->size)); if (!cellptr) return -ENOMEM; /* add new cells to the free cell list */ spin_lock_irqsave(&pool->lock, flags); if (pool->ptr) { spin_unlock_irqrestore(&pool->lock, flags); vfree(cellptr); return 0; } pool->ptr = cellptr; pool->free = NULL; for (cell = 0; cell < pool->size; cell++) { cellptr = pool->ptr + cell; cellptr->pool = pool; cellptr->next = pool->free; pool->free = cellptr; } pool->room = (pool->size + 1) / 2; /* init statistics */ pool->max_used = 0; pool->total_elements = pool->size; spin_unlock_irqrestore(&pool->lock, flags); return 0; }
/* * receive sysex */ void snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset) { struct snd_emux_port *port; struct snd_emux *emu; port = p; if (snd_BUG_ON(!port || !chset)) return; emu = port->emu; switch (parsed) { case SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME: snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME); break; default: if (emu->ops.sysex) emu->ops.sysex(emu, buf, len, parsed, chset); break; } }
static ssize_t snd_compr_read(struct file *f, char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); /* read is allowed when stream is running */ if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { retval = -EBADFD; goto out; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %ld\n", (unsigned long)avail); /* calculate how much we can read from buffer */ if (avail > count) avail = count; if (stream->ops->copy) { retval = stream->ops->copy(stream, buf, avail); } else { retval = -ENXIO; goto out; } if (retval > 0) stream->runtime->total_bytes_transferred += retval; out: mutex_unlock(&stream->device->lock); return retval; }
static int snd_compress_dev_register(struct snd_device *device) { int ret = -EINVAL; struct snd_compr *compr; if (snd_BUG_ON(!device || !device->device_data)) return -EBADFD; compr = device->device_data; pr_debug("reg device %s, direction %d\n", compr->name, compr->direction); /* register compressed device */ ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, compr->device, &snd_compr_file_ops, compr, &compr->dev); if (ret < 0) { pr_err("snd_register_device failed %d\n", ret); return ret; } return ret; }
/* * Queue control via timer control port: * this function is exported as a callback of timer port. */ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) { struct snd_seq_queue *q; if (snd_BUG_ON(!ev)) return -EINVAL; q = queueptr(ev->data.queue.queue); if (q == NULL) return -EINVAL; if (! queue_access_lock(q, ev->source.client)) { queuefree(q); return -EPERM; } snd_seq_queue_process_event(q, ev, atomic, hop); queue_access_unlock(q); queuefree(q); return 0; }
int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substream) { struct snd_kcontrol *kctl; unsigned int idx; int err; if (snd_BUG_ON(!cap_substream)) return -EINVAL; ak4117->substream = cap_substream; for (idx = 0; idx < AK4117_CONTROLS; idx++) { kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117); if (kctl == NULL) return -ENOMEM; kctl->id.device = cap_substream->pcm->device; kctl->id.subdevice = cap_substream->number; err = snd_ctl_add(ak4117->card, kctl); if (err < 0) return err; ak4117->kctls[idx] = kctl; } return 0; }
/* * open port for OSS sequencer */ static int snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) { struct snd_emux *emu; struct snd_emux_port *p; struct snd_seq_port_callback callback; char tmpname[64]; emu = closure; if (snd_BUG_ON(!arg || !emu)) return -ENXIO; if (!snd_emux_inc_count(emu)) return -EFAULT; memset(&callback, 0, sizeof(callback)); callback.owner = THIS_MODULE; callback.event_input = snd_emux_event_oss_input; sprintf(tmpname, "%s OSS Port", emu->name); p = snd_emux_create_port(emu, tmpname, 32, 1, &callback); if (p == NULL) { snd_printk(KERN_ERR "can't create port\n"); snd_emux_dec_count(emu); return -ENOMEM; } /* fill the argument data */ arg->private_data = p; arg->addr.client = p->chset.client; arg->addr.port = p->chset.port; p->oss_arg = arg; reset_port_mode(p, arg->seq_mode); snd_emux_reset_port(p); return 0; }
int snd_ak4114_build(struct ak4114 *ak4114, struct snd_pcm_substream *ply_substream, struct snd_pcm_substream *cap_substream) { struct snd_kcontrol *kctl; unsigned int idx; int err; if (snd_BUG_ON(!cap_substream)) return -EINVAL; ak4114->playback_substream = ply_substream; ak4114->capture_substream = cap_substream; for (idx = 0; idx < AK4114_CONTROLS; idx++) { kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); if (kctl == NULL) return -ENOMEM; if (strstr(kctl->id.name, "Playback")) { if (ply_substream == NULL) { snd_ctl_free_one(kctl); ak4114->kctls[idx] = NULL; continue; } kctl->id.device = ply_substream->pcm->device; kctl->id.subdevice = ply_substream->number; } else { kctl->id.device = cap_substream->pcm->device; kctl->id.subdevice = cap_substream->number; } err = snd_ctl_add(ak4114->card, kctl); if (err < 0) return err; ak4114->kctls[idx] = kctl; } snd_ak4114_proc_init(ak4114); /* trigger workq */ schedule_delayed_work(&ak4114->work, HZ / 10); return 0; }