Esempio n. 1
0
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;
}
Esempio n. 2
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);
}
Esempio n. 3
0
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
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/* 
 * 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;
}
Esempio n. 8
0
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);
}
Esempio n. 12
0
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;
}
Esempio n. 14
0
/*
 * 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);
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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);
}
Esempio n. 18
0
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;

}
Esempio n. 19
0
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;
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
/*
 *  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;
}
Esempio n. 25
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;
}
Esempio n. 26
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;
}
Esempio n. 27
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);
}
Esempio n. 28
0
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;
}