static int q6_aac_flowcontrol(void *data)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	struct aac *aac = data;
	int buff_index = 0;
	int xfer = 0;
	struct aac_fc *fc;


	ac = aac->audio_client;
	fc = aac->aac_fc;
	if (!ac) {
		pr_err("[%s:%s] audio_client is NULL\n", __MM_FILE__, __func__);
		return 0;
	}

	while (!kthread_should_stop()) {
		ab = ac->buf + ac->cpu_buf;
		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));
		pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d\n", __MM_FILE__,
			 __func__, ab->data, ac->cpu_buf);
		xfer = ab->actual_size;

		mutex_lock(&(fc->fc_buff[buff_index].lock));
		if (!fc->fc_buff[buff_index].empty) {
			pr_err("[%s:%s] flow control buffer[%d] not read!\n",
					__MM_FILE__, __func__, buff_index);
		}

		if (fc->fc_buff[buff_index].size < xfer) {
			pr_err("[%s:%s] buffer %d too small\n", __MM_FILE__,
					__func__, buff_index);
			memcpy(fc->fc_buff[buff_index].data,
				ab->data, fc->fc_buff[buff_index].size);
			fc->fc_buff[buff_index].empty = 0;
			fc->fc_buff[buff_index].actual_size =
				fc->fc_buff[buff_index].size;
		} else {
			memcpy(fc->fc_buff[buff_index].data, ab->data, xfer);
			fc->fc_buff[buff_index].empty = 0;
			fc->fc_buff[buff_index].actual_size = xfer;
		}
		mutex_unlock(&(fc->fc_buff[buff_index].lock));
		/*wake up client, if any*/
		wake_up(&fc->fc_wq);

		buff_index++;
		if (buff_index >= AAC_FC_BUFF_CNT)
			buff_index = 0;

		ab->used = 1;

		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}

	return 0;
}
Exemple #2
0
static ssize_t q6_in_read(struct file *file, char __user *buf,
			  size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;
	int res;

	ac = pcm->ac;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
#ifdef CONFIG_EF12_BOARD
				printk("[SKY AUDIO] Dal timeout! maybe timeout or dsp dead.\n");
#else
				audio_client_dump(ac);
				pr_err("[%s:%s] timeout. dsp dead?\n",
						__MM_FILE__, __func__);
				q6audio_dsp_not_responding();
#endif
			}

		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
fail:
	res = buf - start;
	return res;
}
Exemple #3
0
static ssize_t q6_aac_in_read(struct file *file, char __user *buf,
			  size_t count, loff_t *pos)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	struct aac *aac = file->private_data;
	int xfer = 0;
	int res;

	mutex_lock(&aac->lock);
	ac = aac->audio_client;

	if (!ac) {
		res = -ENODEV;
		goto fail;
	}

	ab = ac->buf + ac->cpu_buf;

	if (ab->used)
		wait_event(ac->wait, (ab->used == 0));

	xfer = ab->actual_size;

	if (xfer > count) {

		pr_err("[%s:%s] read failed! byte count too small\n",
				__MM_FILE__, __func__);
		res = -EINVAL;
		goto fail;
	}

	if (copy_to_user(buf, ab->data, xfer)) {
		res = -EFAULT;
		goto fail;
	}

	buf += xfer;

	ab->used = 1;
	q6audio_read(ac, ab);
	ac->cpu_buf ^= 1;

	res = buf - start;
fail:
	mutex_unlock(&aac->lock);

	return res;
}
static ssize_t q6_amrnb_in_read(struct file *file, char __user *buf,
			   size_t count, loff_t *pos)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	struct amrnb *amrnb = file->private_data;
	int xfer = 0;
	int res;

	pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count);
	mutex_lock(&amrnb->lock);
	ac = amrnb->audio_client;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > xfer) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));

		pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d\n", __MM_FILE__,
			__func__, ab->data, ac->cpu_buf);
		xfer = ab->actual_size;

		if (copy_to_user(buf, ab->data, xfer)) {
			pr_err("[%s:%s] copy_to_user failed\n",
				__MM_FILE__, __func__);
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}

	res = buf - start;
fail:
	mutex_unlock(&amrnb->lock);

	return res;
}
static ssize_t q6_in_read(struct file *file, char __user *buf,
			  size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;
	int res;

	ac = pcm->ac;

	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
				audio_client_dump(ac);
				pr_err("pcm_read: timeout. dsp dead?\n");
				BUG();
			}

		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
fail:
	res = buf - start;

	return res;
}
Exemple #6
0
static ssize_t qcelp_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
	 struct audio_client *ac;
	 struct audio_buffer *ab;
	 const char __user *start = buf;
	 int xfer, res = 0;

	 mutex_lock(&qcelp_in_lock);
	 ac = file->private_data;
	 if (!ac) {
		res = -ENODEV;
		pr_err("qcelp_in_read ac NULL\n");
		goto fail;
	 }
	 while (count > 0) {
		ab = ac->buf + ac->cpu_buf;
		TRACE("qcelp_in_read wait count=%d ab=%d ac->buf=%d cpu_buf=%d ac->buf[1]=%d\n",
		      count, ab, ac->buf, ac->cpu_buf, &(ac->buf[1]));
		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));
		TRACE(" qcelp_in_read event arrive ab->size=%d\n", ab->size);
		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			pr_err("Tomdbg copy to user failed \n");
			goto fail;
		}
		TRACE("qcelp_in read buf = %d,xfer = %d,cnt = %d\n", buf, xfer, count);

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	 }
fail:
	 res = buf - start;
	 mutex_unlock(&qcelp_in_lock);
	 return res;
}
Exemple #7
0
static ssize_t q6_evrc_in_read(struct file *file, char __user *buf,
			   size_t count, loff_t *pos)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	struct evrc *evrc = file->private_data;
	int xfer = 0;
	int res;

	mutex_lock(&evrc->lock);
	ac = evrc->audio_client;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > xfer) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));

		xfer = ab->actual_size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}

	res = buf - start;

fail:
	mutex_unlock(&evrc->lock);

	return res;
}
Exemple #8
0
struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,
                                      uint32_t channels, uint32_t flags, uint32_t acdb_id)
{
    int rc, retry = 5;
    struct audio_client *ac;

    if (q6audio_init())
        return 0;

    ac = audio_client_alloc(bufsz);
    if (!ac)
        return 0;

    ac->flags = flags;

    mutex_lock(&audio_path_lock);

    if (ac->flags & AUDIO_FLAG_WRITE) {
        audio_rx_path_refcount++;
        if (audio_rx_path_refcount == 1) {
            _audio_rx_clk_enable();
#ifdef CONFIG_MSM_QDSP6_CALLREC
            q6_rx_path_enable(0, acdb_id);
            adie_rx_path_enable(acdb_id);
#else
            audio_update_acdb(audio_rx_device_id, acdb_id);
            qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE, audio_rx_device_id);
            qdsp6_standby(ac_control);
            qdsp6_start(ac_control);
#endif
        }
    } else {
        /* TODO: consider concurrency with voice call */
#ifdef CONFIG_MSM_QDSP6_CALLREC
        if (audio_tx_path_refcount > 0) {
            tx_clk_freq = 8000;
        } else {
            tx_clk_freq = rate;
        }
#else
        tx_clk_freq = rate;
#endif
        audio_tx_path_refcount++;
        if (audio_tx_path_refcount == 1) {
#ifdef CONFIG_MSM_QDSP6_CALLREC
            tx_clk_freq = rate;
#endif
            _audio_tx_clk_enable();
            _audio_tx_path_enable(0, acdb_id);
        }
    }

    for (retry = 5;; retry--) {
        if (ac->flags & AUDIO_FLAG_WRITE)
            rc = audio_out_open(ac, bufsz, rate, channels);
        else
#ifdef CONFIG_MSM_QDSP6_CALLREC
            rc = audio_in_open(ac, bufsz, flags, rate, channels);
#else
            rc = audio_in_open(ac, bufsz, rate, channels);
#endif
        if (rc == 0)
            break;
        if (retry == 0)
            q6audio_dsp_not_responding();
        pr_err("q6audio: open pcm error %d, retrying\n", rc);
        msleep(1);
    }

    if (ac->flags & AUDIO_FLAG_WRITE) {
        if (audio_rx_path_refcount == 1) {
#ifndef CONFIG_MSM_QDSP6_CALLREC
            adie_enable();
            adie_set_path(adie, audio_rx_path_id, ADIE_PATH_RX);
            adie_set_path_freq_plan(adie, ADIE_PATH_RX, 48000);

            adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_READY);
            adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_ANALOG_READY);

#endif
            audio_rx_analog_enable(1);
        }
    }

    mutex_unlock(&audio_path_lock);

    for (retry = 5;; retry--) {
        rc = audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
        if (rc == 0)
            break;
        if (retry == 0)
            q6audio_dsp_not_responding();
        pr_err("q6audio: stream start error %d, retrying\n", rc);
    }

    if (!(ac->flags & AUDIO_FLAG_WRITE)) {
        ac->buf[0].used = 1;
        ac->buf[1].used = 1;
        q6audio_read(ac, &ac->buf[0]);
        q6audio_read(ac, &ac->buf[1]);
    }

    audio_prevent_sleep();
    return ac;
}
Exemple #9
0
static int snd_qsd_fake_capture_dma_thread(void *data)
{
    int rc = 0;
    int rcopy;
    struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
    struct snd_pcm_runtime *runtime = substream->runtime;
    struct qsd_audio *prtd = runtime->private_data;

    struct audio_buffer *ab;
    struct audio_client *ac;
    unsigned char *ptr;

    while (prtd->thread_exit == 0)
    {
        DBG(" start handler");

        // wait until state is changed
        // at this point this thread waits until SNDRV_PCM_TRIGGER_START comes
        // SNDRV_PCM_TRIGGER_STOP
        //
        wait_event_interruptible(prtd->fake_wait, (prtd->start == 1 || prtd->thread_exit == 1));
        DBG("  wake up %d %d", prtd->start, prtd->thread_exit);

        if (prtd->thread_exit) break;

        ac = prtd->ac;
        while (prtd->start == 1)
        {
            //  wait until new buffer appear
            //
            //            DBG("  ac = %X, prtd = %X, substream = %X", ac, prtd, substream);

            ab = ac->buf + ac->cpu_buf;
            if (ab->used)
            {
                DBG("wait a buffer %d", ac->cpu_buf);
                if (!wait_event_timeout(ac->wait, (ab->used == 0), 5 * HZ))
                {
                    DBG("timeout. dsp dead?\n");
                    rc = -EFAULT;
                    goto fail;
                }

                // some buffer become free, report about state change now
                //
                snd_pcm_period_elapsed(prtd->substream);
            }

            mutex_lock(&prtd->mlock);

            if (prtd->start == 0)
            {
                DBG("flag is set - exit thread");
                mutex_unlock(&prtd->mlock);
                break;    // EXIT FROM LOOP
            }

            // this buffer must contains recorded data
            // copy it to dma buffer
            //
            ptr = runtime->dma_area + prtd->buf_curoff;
            rcopy = prtd->buf_chunk;
            if (rcopy > ab->size)
                rcopy = ab->size;
            memcpy(ptr, ab->data, rcopy);


            // send this buffer to DSP queue again
            //
            ab->used = rcopy;
            q6audio_read(ac, ab);
            ac->cpu_buf ^= 1;


            // move fake dma pointer forward
            //
            spin_lock(&prtd->lock);
            prtd->buf_curoff += prtd->buf_chunk;
            if (prtd->buf_curoff >= prtd->buf_maxoff)
                prtd->buf_curoff = 0;
            spin_unlock(&prtd->lock);

            mutex_unlock(&prtd->mlock);

fail:
            ; // CotullaTODO: handle this fault somehow.
        }
        DBG(" end handler");
    }
    DBG(" exit");
    return 0;
}
static ssize_t q6_amrnb_in_read(struct file *file, char __user *buf,
			   size_t count, loff_t *pos)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	struct amrnb *amrnb = file->private_data;
	int xfer = 0;
	int res;

	mutex_lock(&amrnb->lock);
	ac = amrnb->audio_client;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
#if 1 
	while (count > xfer) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));

		xfer = ab->actual_size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
#else
        while (count > 0) {
                ab = ac->buf + ac->cpu_buf;

                if (ab->used)
			 wait_event(ac->wait, (ab->used == 0));
#if 0
                        if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
                                audio_client_dump(ac);
                                pr_err("pcm_read: timeout. dsp dead?\n");
                                q6audio_dsp_not_responding();
                        }
#endif
                xfer = count;
                if (xfer > ab->size)
                        xfer = ab->size;

                if (copy_to_user(buf, ab->data, xfer)) {
                        res = -EFAULT;
                        goto fail;
                }

                buf += xfer;
                count -= xfer;

                ab->used = 1;
                q6audio_read(ac, ab);
                ac->cpu_buf ^= 1;
        }
#endif

	res = buf - start;
fail:
	mutex_unlock(&amrnb->lock);

	return res;
}