static int saudio_ctrl_thread(void *data) { int result = 0; struct snd_saudio *saudio = (struct snd_saudio *)data; ADEBUG(); result = saudio_snd_init_ipc(saudio); if (result) { printk(KERN_ERR "saudio:saudio_snd_init_ipc error %d\n", result); return -1; } while (!kthread_should_stop()) { printk(KERN_INFO "%s,saudio: waiting for modem boot handshake,dst %d,channel %d\n", __func__, saudio->dst, saudio->channel); saudio_snd_wait_modem_restart(saudio); saudio->in_init = 1; printk(KERN_INFO "%s,saudio: modem boot and handshake ok,dst %d, channel %d\n", __func__, saudio->dst, saudio->channel); saudio_snd_card_free(saudio); printk(KERN_INFO "saudio_ctrl_thread flush work queue in dst %d, channel %d\n", saudio->dst, saudio->channel); flush_workqueue(saudio->queue); saudio->in_init = 0; printk(KERN_INFO "saudio_ctrl_thread flush work queue out,dst %d, channel %d\n", saudio->dst, saudio->channel); if(saudio_snd_notify_modem_clear(saudio)) { printk(KERN_ERR " saudio_ctrl_thread modem error again when notify modem clear \n"); continue; } saudio_clear_ctrl_cmd(saudio); if(!saudio->card) { result = saudio_snd_init_card(saudio); printk(KERN_INFO "saudio: snd card init reulst %d, dst %d, channel %d\n", result, saudio->dst, saudio->channel); } mutex_lock(&saudio->mutex); saudio->state = 1; mutex_unlock(&saudio->mutex); } ETRACE("saudio_ctrl_thread create ok\n"); return 0; }
static void __exit omap_alsa_tsc2101_exit(void) { ADEBUG(); #ifdef DUMP_TSC2101_AUDIO_REGISTERS printk(KERN_INFO "omap_alsa_tsc2101_exit()\n"); dump_tsc2101_audio_reg(); #endif platform_driver_unregister(&omap_alsa_driver); }
static int snd_card_saudio_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct saudio_dev_ctrl *dev_ctrl = NULL; struct saudio_stream *stream = NULL; struct saudio_msg msg = { 0 }; int err = 0; int result = 0; ADEBUG(); dev_ctrl = (struct saudio_dev_ctrl *)&(saudio->dev_ctrl[dev]); stream = (struct saudio_stream *)&(dev_ctrl->stream[stream_id]); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: msg.stream_id = stream_id; stream->stream_state = SAUDIO_TRIGGERED; result = saudio_data_trigger_process(stream, &msg); result = saudio_send_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_START, stream->stream_id,0); if (result) { ETRACE("saudio.c: snd_card_saudio_pcm_trigger: RESUME, send_common_cmd result is %d", result); saudio_snd_card_free(saudio); return result; } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: stream->stream_state = SAUDIO_STOPPED; result = saudio_send_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_STOP, stream->stream_id, 0); if (result) { ETRACE("saudio.c: snd_card_saudio_pcm_trigger: SUSPEND, send_common_cmd result is %d", result); saudio_snd_card_free(saudio); return result; } break; default: err = -EINVAL; break; } return 0; }
static int vaudio_snd_hw_free (struct snd_pcm_substream* substream) { ADEBUG(); #ifdef VAUDIO_CONFIG_NK_PMEM return vaudio_pcm_lib_free_pages(substream); #else return snd_pcm_lib_free_pages(substream); #endif }
static int audio_dma_free(struct audio_stream *s) { int err = 0; ADEBUG(); err = omap_free_alsa_sound_dma(s, &s->lch); if (err < 0) printk(KERN_ERR "Unable to free audio dma channels!\n"); return err; }
static int snd_card_saudio_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int32_t result = 0; ADEBUG(); result = saudio_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); pr_debug("saudio.c: saudio.c: hw_params result is %d", result); return result; }
/* * DMA functions * Depends on omap-alsa-dma.c functions and (omap) dma.c * */ static int audio_dma_request(struct audio_stream *s, void (*callback) (void *)) { int err; ADEBUG(); err = omap_request_alsa_sound_dma(s->dma_dev, s->id, s, &s->lch); if (err < 0) printk(KERN_ERR "Unable to grab audio dma 0x%x\n", s->dma_dev); return err; }
static int snd_card_saudio_pcm_open(struct snd_pcm_substream *substream) { const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct snd_pcm_runtime *runtime = substream->runtime; struct saudio_stream *stream = NULL; int result = 0; struct saudio_dev_ctrl *dev_ctrl = NULL; ADEBUG(); pr_info("%s IN, stream_id=%d\n", __func__, stream_id); dev_ctrl = (struct saudio_dev_ctrl *)&(saudio->dev_ctrl[dev]); stream = (struct saudio_stream *)&(dev_ctrl->stream[stream_id]); stream->substream = substream; stream->stream_id = stream_id; stream->period = 0; stream->periods_tosend = 0; stream->periods_avail = 0; stream->hwptr_done = 0; stream->last_getblk_count = 0; stream->last_elapsed_count = 0; stream->blk_count = SAUDIO_STREAM_BLOCK_COUNT; if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { runtime->hw = snd_card_saudio_playback; } else { runtime->hw = snd_card_saudio_capture; } mutex_lock(&dev_ctrl->mutex); saudio_clear_ctrl_cmd(saudio); result = saudio_send_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_OPEN, stream_id,CMD_TIMEOUT); if (result) { ETRACE("saudio.c: snd_card_saudio_pcm_open: saudio_send_common_cmd result is %d", result); saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); return result; } pr_info("%s send cmd done\n", __func__); result = saudio_wait_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_OPEN_RET, 0,CMD_TIMEOUT); if(result) saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); pr_info("%s OUT, result=%d\n", __func__, result); return result; }
static void __exit vaudio_exit (void) { ADEBUG(); #if VAUDIO_PROC_SYNC vaudio_proc_delete("close"); #endif vaudio_thread_aborted = 1; up (&vaudio_thread_sem); wait_for_completion (&vaudio_thread_completion); snd_card_free(vaudio_card); }
static int vaudio_snd_hw_params (struct snd_pcm_substream* substream, struct snd_pcm_hw_params* hw_params) { ADEBUG(); #ifdef VAUDIO_CONFIG_NK_PMEM return vaudio_pcm_lib_malloc_pages (substream, params_buffer_bytes(hw_params)); #else return snd_pcm_lib_malloc_pages (substream, params_buffer_bytes(hw_params)); #endif }
static snd_pcm_uframes_t vaudio_snd_pointer (struct snd_pcm_substream* substream) { const NkVaudio chip = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct vaudio_stream* s = &chip->s[dev][stream_id]; struct snd_pcm_runtime* runtime = substream->runtime; unsigned int offset; ADEBUG(); offset = s->hwptr_done * frames_to_bytes(runtime, runtime->period_size); return bytes_to_frames(runtime, offset); }
static int snd_card_saudio_hw_free(struct snd_pcm_substream *substream) { int ret=0; const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct saudio_stream *stream = (struct saudio_stream *)&(saudio->dev_ctrl[dev].stream[stream_id]); ADEBUG(); mutex_lock(&stream->mutex); ret = saudio_pcm_lib_free_pages(substream); mutex_unlock(&stream->mutex); return ret; }
static int vaudio_snd_trigger (struct snd_pcm_substream* substream, int cmd) { const NkVaudio chip = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct vaudio_stream* s = &chip->s[dev][stream_id]; struct snd_pcm_runtime* runtime = substream->runtime; NkVaudioCtrl* ctrl = s->ctrl; NkDevVlink* vlink = chip->vlink; ADEBUG(); /* Local interrupts are already disabled in the midlevel code */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* Requested stream startup */ s->active = 1; if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { s->periods_avail = snd_pcm_playback_avail(runtime) / runtime->period_size; } else { s->periods_avail = snd_pcm_capture_avail(runtime) / runtime->period_size; } s->periods_tosend = runtime->periods - s->periods_avail; while (s->periods_tosend) { if (vaudio_send_data(s) < 0) break; s->periods_tosend--; } ctrl->command = NK_VAUDIO_COMMAND_START; nkops.nk_xirq_trigger(ctrl->cxirq, vlink->s_id); /* This command is asynchronous, no waiting on down() */ return 0; case SNDRV_PCM_TRIGGER_STOP: /* Requested stream shutdown */ s->active = 0; ctrl->command = NK_VAUDIO_COMMAND_STOP; nkops.nk_xirq_trigger(ctrl->cxirq, vlink->s_id); /* This command is asynchronous, no waiting on down() */ return 0; default: break; } return -EINVAL; }
/* * this stops the dma and clears the dma ptrs */ static void audio_stop_dma(struct audio_stream *s) { unsigned long flags; ADEBUG(); spin_lock_irqsave(&s->dma_lock, flags); s->active = 0; s->period = 0; s->periods = 0; /* this stops the dma channel and clears the buffer ptrs */ omap_stop_alsa_sound_dma(s); omap_clear_alsa_sound_dma(s); spin_unlock_irqrestore(&s->dma_lock, flags); }
bool AdbConnection::retrieveFileData(AdbFile* af, AdbConReply* r){ if(!r) return false; bool x = false; switch(r->code){ case rFILE: x = af->parse(r->data); x = true; break; case rNO_SUCH_FILE: ALOG(wxT("The file does not exist in AniDB.")); break; default: ADEBUG(r->message); } delete r; return x; }
static int snd_card_saudio_pcm_close(struct snd_pcm_substream *substream) { const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct saudio_dev_ctrl *dev_ctrl = NULL; int result = 0; ADEBUG(); mutex_lock(&saudio->mutex); if(!saudio->state) { mutex_unlock(&saudio->mutex); printk("saudio.c: snd_pcm_close error saudio state %d\n",saudio->state); return -EIO; } mutex_unlock(&saudio->mutex); dev_ctrl = (struct saudio_dev_ctrl *)&(saudio->dev_ctrl[dev]); pr_info("%s IN, stream_id=%d,dst %d, channel %d\n", __func__, stream_id, dev_ctrl->dst, dev_ctrl->channel); mutex_lock(&dev_ctrl->mutex); result = saudio_send_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_CLOSE, stream_id, CMD_TIMEOUT); if (result) { ETRACE ("saudio.c: snd_card_saudio_pcm_close: saudio_send_common_cmd result is %d", result); if(result != (-ERESTARTSYS)) saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); return result; } pr_info("%s send cmd done\n", __func__); result = saudio_wait_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_CLOSE_RET, 0, CMD_TIMEOUT); if (result && (result != (-ERESTARTSYS))) saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); pr_info("%s OUT, result=%d,dst %d, channel %d\n", __func__, result, dev_ctrl->dst, dev_ctrl->channel); return result; }
static int vaudio_snd_mmap (struct snd_pcm_substream* substream, struct vm_area_struct *vma) { const NkVaudio chip = snd_pcm_substream_chip(substream); const int dev = substream->pcm->device; const int stream_id = substream->pstr->stream; struct vaudio_stream* s = &chip->s[dev][stream_id]; ADEBUG(); if (s->use_dma) { vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); } return remap_pfn_range(vma, vma->vm_start, substream->dma_buffer.addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); }
static int saudio_cmd_prepare_process(struct saudio_dev_ctrl *dev_ctrl, struct saudio_msg *msg) { struct sblock blk; struct snd_saudio *saudio=NULL; int32_t result = 0; struct snd_pcm_runtime *runtime = dev_ctrl->stream[msg->stream_id].substream->runtime; ADEBUG(); saudio = dev_ctrl->stream[msg->stream_id].saudio; result = sblock_get(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk, CMD_TIMEOUT); if (!result) { struct cmd_prepare *prepare = (struct cmd_prepare *)blk.addr; prepare->common.command = SAUDIO_CMD_PREPARE; prepare->common.sub_cmd=msg->stream_id; prepare->rate = runtime->rate; prepare->channels = runtime->channels; prepare->format = runtime->format; prepare->period = frames_to_bytes(runtime, runtime->period_size); prepare->periods = runtime->periods; blk.length = sizeof(struct cmd_prepare); mutex_lock(&dev_ctrl->mutex); sblock_send(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk); result = saudio_wait_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_PREPARE_RET, 0,CMD_TIMEOUT); if(result) saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); } pr_debug("saudio_cmd_prepare_process result is %d", result); return result; }
static int snd_card_saudio_pcm_prepare(struct snd_pcm_substream *substream) { const struct snd_saudio *saudio = snd_pcm_substream_chip(substream); const int stream_id = substream->pstr->stream; const int dev = substream->pcm->device; struct saudio_dev_ctrl *dev_ctrl = NULL; struct saudio_msg msg = { 0 }; int result = 0; ADEBUG(); dev_ctrl = (struct saudio_dev_ctrl *)&(saudio->dev_ctrl[dev]); msg.command = SAUDIO_CMD_PREPARE; msg.stream_id = stream_id; result = saudio_cmd_prepare_process(dev_ctrl, &msg); return 0; }
static int __init vaudio_init (void) { ADEBUG(); sema_init(&vaudio_thread_sem, 0); if (vaudio_snd_probe() < 0) { ETRACE ("virtual audio ALSA card initialization failed\n"); return -ENODEV; } vaudio_thread_id = kernel_thread(vaudio_thread, 0, 0); if (vaudio_thread_id < 0) { ETRACE ("virtual audio kernel thread creation failure \n"); return vaudio_thread_id; } #if VAUDIO_PROC_SYNC vaudio_proc_create("close"); #endif return 0; }
static int vaudio_snd_card_open (struct snd_pcm_substream* substream) { const NkVaudio chip = snd_pcm_substream_chip(substream); const int dev = substream->pcm->device; const int stream_id = substream->pstr->stream; struct vaudio_stream* s = &chip->s[dev][stream_id]; struct snd_pcm_runtime* runtime = substream->runtime; NkVaudioCtrl* ctrl = s->ctrl; NkDevRing* ring = s->ring; NkDevVlink* vlink = chip->vlink; ADEBUG(); s->stream = substream; s->stream_id = stream_id; s->hwptr_done = 0; s->period = 0; s->resp = 0; ring->ireq = 0; ring->iresp = 0; if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { runtime->hw = vaudio_snd_playback[dev][stream_id]; ctrl->session_type = NK_VAUDIO_SS_TYPE_PLAYBACK; } else { runtime->hw = vaudio_snd_capture[dev][stream_id]; ctrl->session_type = NK_VAUDIO_SS_TYPE_CAPTURE; } ctrl->stream_type = NK_VAUDIO_ST_TYPE_PCM; ctrl->command = NK_VAUDIO_COMMAND_OPEN; nkops.nk_xirq_trigger(ctrl->cxirq, vlink->s_id); down(&s->ctrl_sem); #if VAUDIO_PROC_SYNC if (/*dev == 0 && */stream_id == SNDRV_PCM_STREAM_CAPTURE) { mutex_lock(&vaudio_proc_sync_lock); vrs = s; mutex_unlock(&vaudio_proc_sync_lock); } #endif return ctrl->status; }
static int saudio_send_common_cmd(uint32_t dst, uint32_t channel, uint32_t cmd, uint32_t subcmd, int32_t timeout) { int result = 0; struct sblock blk = { 0 }; ADEBUG(); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x\n", dst, channel, cmd, subcmd); saudio_clear_cmd( dst, channel); result = sblock_get(dst, channel, (struct sblock *)&blk, timeout); if (result >= 0) { struct cmd_common *common = (struct cmd_common *)blk.addr; common->command = cmd; common->sub_cmd = subcmd; blk.length = sizeof(struct cmd_common); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x send ok\n", dst, channel, cmd, subcmd); result = sblock_send(dst, channel, (struct sblock *)&blk); } return result; }
/* * Main dma routine, requests dma according where you are in main alsa buffer */ static void audio_process_dma(struct audio_stream *s) { struct snd_pcm_substream *substream = s->stream; struct snd_pcm_runtime *runtime; unsigned int dma_size; unsigned int offset; int ret; ADEBUG(); runtime = substream->runtime; if (s->active) { dma_size = frames_to_bytes(runtime, runtime->period_size); offset = dma_size * s->period; snd_assert(dma_size <= DMA_BUF_SIZE,); /* * On omap1510 based devices, we need to call the stop_dma * before calling the start_dma or we will not receive the * irq from DMA after the first transfered/played buffer. * (invocation of callback_omap_alsa_sound_dma() method). */ if (cpu_is_omap1510()) { omap_stop_alsa_sound_dma(s); } ret = omap_start_alsa_sound_dma(s, (dma_addr_t)runtime->dma_area + offset, dma_size); if (ret) { printk(KERN_ERR "audio_process_dma: cannot queue DMA buffer (%i)\n", ret); return; } s->period++; s->period %= runtime->periods; s->periods++; s->offset = offset; }
static int __init vaudio_snd_card_pcm (NkVaudio vaudio, int device) { struct snd_pcm* pcm; int err; ADEBUG(); if ((err = snd_pcm_new(vaudio->card, "VAUDIO PCM", device, 1, 1, &pcm)) < 0) return err; pcm->private_data = vaudio; /* Set up initial buffer with continuous allocation */ #ifdef VAUDIO_CONFIG_NK_PMEM pcm->private_free = vaudio_pcm_lib_preallocate_free_for_all; vaudio_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), NK_VAUDIO_MAX_RING_SIZE, NK_VAUDIO_MAX_RING_SIZE); #else snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), NK_VAUDIO_MAX_RING_SIZE, NK_VAUDIO_MAX_RING_SIZE); #endif snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vaudio_snd_card_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vaudio_snd_card_capture_ops); pcm->info_flags = 0; snprintf (pcm->name, sizeof pcm->name, "virtual audio pcm"); vaudio->pcm[device] = pcm; return 0; }
static int __devinit snd_saudio_probe(struct platform_device *devptr) { struct snd_saudio *saudio = NULL; static pid_t thread_id = (pid_t) -1; struct saudio_init_data *init_data = devptr->dev.platform_data; ADEBUG(); if (!(saudio = saudio_card_probe(init_data))) { return -1; } saudio->pdev = devptr; saudio->queue=create_singlethread_workqueue("saudio"); if(!saudio->queue) { printk("saudio:workqueue create error %d",saudio->queue); if(saudio) { kfree(saudio); saudio = NULL; } return -1; } printk("saudio:workqueue create ok"); INIT_WORK(&saudio->card_free_work,saudio_work_card_free_handler); platform_set_drvdata(devptr, saudio); thread_id = kernel_thread(saudio_ctrl_thread, saudio, 0); if (thread_id < 0) { ETRACE("virtual audio cmd kernel thread creation failure \n"); destroy_workqueue(saudio->queue); saudio->queue = NULL; kfree(saudio); platform_set_drvdata(devptr, NULL); return thread_id; } return 0; }
static int snd_saudio_probe(struct platform_device *devptr) { struct snd_saudio *saudio = NULL; static pid_t thread_id = (pid_t) - 1; #ifdef CONFIG_OF int ret, id; const char *name = NULL; struct saudio_init_data snd_init_data = {0}; const char *saudio_names = "sprd,saudio-names"; const char *saudio_dst_id = "sprd,saudio-dst-id"; struct saudio_init_data *init_data = &snd_init_data; #else struct saudio_init_data *init_data = devptr->dev.platform_data; #endif ADEBUG(); #ifdef CONFIG_OF ret = of_property_read_u32(devptr->dev.of_node, saudio_dst_id, &id); if (ret) { printk("saudio: %s: missing %s in dt node\n", __func__, saudio_dst_id); return ret; } else { if ((id == SIPC_ID_CPT) || (id == SIPC_ID_CPW)) { printk("saudio: %s: %s is %d\n", __func__, __func__, saudio_dst_id, id); } else { printk("saudio: %s: %s is %d and only support 1,2\n", __func__, saudio_dst_id, id); return ret; } } ret = of_property_read_string(devptr->dev.of_node, saudio_names, &name); if (ret) { printk("saudio: %s: missing %s in dt node\n", __func__, saudio_names); return ret; } else { printk("saudio: %s: %s is %s\n", __func__, __func__, saudio_names, name); } if (!strcmp(name, "saudio_voip")) { init_data->name = "saudiovoip"; init_data->dst = id; init_data->ctrl_channel = SMSG_CH_CTRL_VOIP; init_data->playback_channel = SMSG_CH_PLAYBACK_VOIP; init_data->capture_channel = SMSG_CH_CAPTURE_VOIP; init_data->monitor_channel = SMSG_CH_MONITOR_VOIP; } else if(id == SIPC_ID_CPT) { init_data->name = "VIRTUAL AUDIO"; init_data->dst = id; init_data->ctrl_channel = SMSG_CH_VBC; init_data->playback_channel = SMSG_CH_PLAYBACK; init_data->capture_channel = SMSG_CH_CAPTURE; init_data->monitor_channel = SMSG_CH_MONITOR_AUDIO; } else if(id == SIPC_ID_CPW) { init_data->name = "VIRTUAL AUDIO W"; init_data->dst = id; init_data->ctrl_channel = SMSG_CH_VBC; init_data->playback_channel = SMSG_CH_PLAYBACK; init_data->capture_channel = SMSG_CH_CAPTURE; init_data->monitor_channel = SMSG_CH_MONITOR_AUDIO; } else { printk("saudio: %s: get data in dt node failed\n", __func__); } #endif if (!(saudio = saudio_card_probe(init_data))) { return -1; } saudio->pdev = devptr; saudio->queue = create_singlethread_workqueue("saudio"); if (!saudio->queue) { printk("saudio:workqueue create error %d\n", (int)saudio->queue); if (saudio) { kfree(saudio); saudio = NULL; } return -1; } printk("saudio:workqueue create ok"); INIT_WORK(&saudio->card_free_work, saudio_work_card_free_handler); platform_set_drvdata(devptr, saudio); saudio->thread_id = kthread_create(saudio_ctrl_thread, saudio, "saudio-%d-%d",saudio->dst,saudio->channel); if (IS_ERR(saudio->thread_id)) { ETRACE("virtual audio cmd kernel thread creation failure \n"); destroy_workqueue(saudio->queue); saudio->queue = NULL; saudio->thread_id = NULL; kfree(saudio); platform_set_drvdata(devptr, NULL); return -1; } wake_up_process(saudio->thread_id); return 0; }
/* * Sample rate changing */ void tsc2101_set_samplerate(long sample_rate) { u8 count = 0; u16 data = 0; int clkgdv = 0; u16 srgr1, srgr2; /* wait for any frame to complete */ udelay(125); ADEBUG(); sample_rate = sample_rate; /* Search for the right sample rate */ while ((rate_reg_info[count].sample_rate != sample_rate) && (count < NUMBER_SAMPLE_RATES_SUPPORTED)) { count++; } if (count == NUMBER_SAMPLE_RATES_SUPPORTED) { printk(KERN_ERR "Invalid Sample Rate %d requested\n", (int) sample_rate); return; // -EPERM; } /* Set AC1 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1); /* Clear prev settings */ data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07)); data |= AC1_DACFS(rate_reg_info[count].divisor) | AC1_ADCFS(rate_reg_info[count].divisor); tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data); /* Set the AC3 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3); /*Clear prev settings */ data &= ~(AC3_REFFS | AC3_SLVMS); data |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0; #ifdef TSC_MASTER data |= AC3_SLVMS; #endif /* #ifdef TSC_MASTER */ tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data); /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use. * If MCLK rate is something else, these values must be changed. * See the tsc2101 specification for the details. */ if (rate_reg_info[count].fs_44kHz) { /* samplerate = (44.1kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */ } else { /* samplerate = (48.kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */ } /* Set the sample rate */ #ifndef TSC_MASTER clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1)); if (clkgdv) srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); else return (1); /* Stereo Mode */ srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)); #else srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1))); #endif /* end of #ifdef TSC_MASTER */ OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2); OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1); }
static int saudio_snd_init_card(struct snd_saudio *saudio) { int result = 0; int32_t i = 0, j = 0, err = 0; struct saudio_stream *stream = NULL; struct saudio_dev_ctrl *dev_ctrl = NULL; struct snd_card *saudio_card = NULL; ADEBUG(); if(!saudio) { return -1; } result = snd_card_create(SNDRV_DEFAULT_IDX1, saudio->dev_ctrl[0].name, THIS_MODULE, sizeof( struct snd_saudio *), &saudio_card); if(!saudio_card) { printk(KERN_ERR "saudio:snd_card_create faild result is %d\n",result); return -1; } saudio->card = saudio_card; saudio_card->private_data = saudio; for (i = 0; i < SAUDIO_DEV_MAX; i++) { dev_ctrl = &saudio->dev_ctrl[i]; mutex_init(&dev_ctrl->mutex); err = snd_card_saudio_pcm(saudio, i, 1); if (err < 0) goto __nodev; for (j = 0; j < SAUDIO_STREAM_MAX; j++) { stream = &dev_ctrl->stream[j]; stream->dev_ctrl = dev_ctrl; stream->saudio = saudio; stream->stream_state = SAUDIO_IDLE; stream->stream_id = j; mutex_init(&stream->mutex); } } ADEBUG(); memcpy(saudio->card->driver, dev_ctrl->name, SAUDIO_CARD_NAME_LEN_MAX); memcpy(saudio->card->shortname, dev_ctrl->name, SAUDIO_CARD_NAME_LEN_MAX); memcpy(saudio->card->longname, dev_ctrl->name, SAUDIO_CARD_NAME_LEN_MAX); err = snd_card_register(saudio->card); if (err == 0) { ETRACE("snd_card create ok\n"); return 0; } __nodev: if(saudio) { if(saudio->card) { snd_card_free(saudio->card); } } ETRACE("initialization failed\n"); return err; }
static int vaudio_snd_probe (void) { NkPhAddr pdev; NkDevVlink* vlink; NkPhAddr plink = 0; NkXIrq cxirq; NkXIrq pxirq; NkVaudioMixer* mixer; const size_t pdev_size = sizeof(NkDevRing) + sizeof(NkVaudioHw) + sizeof(NkVaudioCtrl) + NK_VAUDIO_RING_DESC_NB * sizeof(NkRingDesc); int cur_stream; int i, j; const NkOsId my_id = nkops.nk_id_get(); char* resinfo; char* info; int slot; #ifdef VAUDIO_CONFIG_NK_PMEM NkPhAddr ring_buf_p; int ring_size; #endif ADEBUG(); /* * Find the communication vlink. */ while ((plink = nkops.nk_vlink_lookup("vaudio", plink))) { vlink = nkops.nk_ptov(plink); if (vlink->c_id == my_id) { break; } } if (!plink) { return -ENODEV; } if (vlink->c_info != 0) { info = (char*) nkops.nk_ptov(vlink->c_info); slot = simple_strtoul(info, &resinfo, 0); if (resinfo == info) { slot = -1; } } else { slot = -1; } /* * Perform initialization of NK virtual audio device. */ pdev = nkops.nk_pdev_alloc (plink, 0, NK_VAUDIO_STREAMS_NB * pdev_size + sizeof(NkVaudioMixer)); if (!pdev) { return -ENOMEM; } /* * Allocate cross-interrupts. */ cxirq = nkops.nk_pxirq_alloc(plink, 0, vlink->s_id, 2 * NK_VAUDIO_STREAMS_NB + 1); if (!cxirq) { return -ENOMEM; } pxirq = nkops.nk_pxirq_alloc(plink, 1, vlink->c_id, 2 * NK_VAUDIO_STREAMS_NB + 1); if (!pxirq) { return -ENOMEM; } /* Register the sound-card */ #if LINUX_VERSION_CODE > KERNEL_VERSION (2,6,29) { int err = snd_card_create (slot, "VAUDIO", THIS_MODULE, sizeof *vaudio, &vaudio_card); if (err) { return err; } } #else vaudio_card = snd_card_new (slot, "VAUDIO", THIS_MODULE, sizeof *vaudio); if (!vaudio_card) { return -ENOMEM; } #endif /* * Perform vaudio initialization. * Code relies on *vaudio being zeroed by the alloc call above. */ vaudio = vaudio_card->private_data; vaudio_card->private_free = vaudio_snd_free; vaudio->card = vaudio_card; vaudio->vlink = vlink; vaudio->sysconf_xid = nkops.nk_xirq_attach(NK_XIRQ_SYSCONF, vaudio_sysconf_intr, vaudio); if (!vaudio->sysconf_xid) { snd_card_free(vaudio_card); return -EINVAL; } sema_init(&vaudio->mixer_sem, 0); #ifdef VAUDIO_CONFIG_NK_PMEM /* * The DMA ring buffer is allocated in the PMEM. */ ring_size = NK_VAUDIO_MAX_RING_SIZE; ring_buf_p = nkops.nk_pmem_alloc(plink, 0, NK_VAUDIO_STREAMS_NB * ring_size); if (ring_buf_p == 0) { ETRACE ("Cannot alloc %d bytes of pmem\n", NK_VAUDIO_STREAMS_NB * ring_size); snd_card_free(vaudio_card); return -ENOMEM; } #endif /* * Perform stream initialization. */ cur_stream = 0; for (i = 0; i < NK_VAUDIO_DEV_MAX; i++) { for (j = 0; j < NK_VAUDIO_STREAM_MAX; j++) { NkDevRing* ring; NkVaudioCtrl* control; vaudio->s[i][j].vaudio = vaudio; sema_init(&vaudio->s[i][j].ctrl_sem, 0); /* * Perform initialization of the descriptor ring. */ ring = nkops.nk_ptov(pdev + cur_stream); ring->cxirq = cxirq++; ring->pxirq = pxirq++; ring->dsize = sizeof(NkRingDesc); ring->imask = NK_VAUDIO_RING_DESC_NB - 1; vaudio->s[i][j].ring = ring; vaudio->s[i][j].ring_xid = nkops.nk_xirq_attach(ring->pxirq, vaudio_intr_data, &vaudio->s[i][j]); if (!vaudio->s[i][j].ring_xid) { snd_card_free(vaudio_card); return -EINVAL; } /* * Initialize hardware config pointer. */ vaudio->s[i][j].hw_conf = nkops.nk_ptov(pdev + cur_stream + sizeof(NkDevRing)); /* * Perform initialization of control. */ control = nkops.nk_ptov(pdev + cur_stream + sizeof(NkDevRing) + sizeof(NkVaudioHw)); control->cxirq = cxirq++; control->pxirq = pxirq++; vaudio->s[i][j].ctrl = control; vaudio->s[i][j].ctrl_xid = nkops.nk_xirq_attach(control->pxirq, vaudio_intr_ctrl, &vaudio->s[i][j]); if (!vaudio->s[i][j].ctrl_xid) { snd_card_free(vaudio_card); return -EINVAL; } /* * Set ring descriptor base address. */ vaudio->s[i][j].resp = 0; vaudio->s[i][j].rbase = nkops.nk_ptov(pdev + cur_stream + sizeof(NkDevRing) + sizeof(NkVaudioHw) + sizeof(NkVaudioCtrl)); #ifdef VAUDIO_CONFIG_NK_PMEM /* * The DMA ring buffer is allocated in the PMEM. */ vaudio->s[i][j].ring_buf_p = ring_buf_p; vaudio->s[i][j].ring_buf_v = (unsigned char*) nkops.nk_mem_map(ring_buf_p, ring_size); ring_buf_p += ring_size; #endif cur_stream += pdev_size; } } /* * Perform initialization of mixer. */ mixer = nkops.nk_ptov(pdev + NK_VAUDIO_STREAMS_NB * pdev_size); mixer->cxirq = cxirq; mixer->pxirq = pxirq; vaudio->mixer = mixer; vaudio->mixer_xid = nkops.nk_xirq_attach(mixer->pxirq, vaudio_intr_mixer, vaudio); if (!vaudio->mixer_xid) { snd_card_free(vaudio_card); return -EINVAL; } /* * Perform handshake until both links are ready. */ vaudio_handshake(vaudio); return 0; }