示例#1
0
static int qsd_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
				 snd_pcm_uframes_t hwoff, void __user *buf,
				 snd_pcm_uframes_t frames)
{
	int fbytes = 0;
	size_t xfer;
	int rc;

	struct snd_pcm_runtime *runtime = substream->runtime;
	struct qsd_audio *prtd = runtime->private_data;

	fbytes = frames_to_bytes(runtime, frames);
	prtd->cbs.buffer = (void *)buf;
	prtd->cbs.phys_addr = 0;
	prtd->cbs.max_size = fbytes;
	prtd->cbs.actual_size = fbytes;

	prtd->pcm_buf_pos += fbytes;
	mutex_lock(&the_locks.lock);
	xfer = cad_write(prtd->cad_w_handle, &prtd->cbs);
	mutex_unlock(&the_locks.lock);

	mutex_lock(&the_locks.mixer_lock);
	if (qsd_glb_ctl.update) {
		rc = qsd_audio_volume_update(prtd);
		qsd_glb_ctl.update = 0;
	}
	mutex_unlock(&the_locks.mixer_lock);

	return 0;
}
示例#2
0
static int snd_qsd_fake_playback_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
            }

            // send buffer to DSP
            //
            ptr = runtime->dma_area + prtd->buf_curoff;
            rcopy = prtd->buf_chunk;
            if (rcopy > ab->size)
                rcopy = ab->size;

            memcpy(ab->data, ptr, rcopy);
            ab->used = rcopy;
            q6audio_write(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);


            // update stream settings if required
            //
            if (qsd_glb_ctl.update)
            {
                rc = qsd_audio_volume_update(prtd);
                qsd_glb_ctl.update = 0;
            }

            mutex_unlock(&prtd->mlock);

fail:
            ; // CotullaTODO: handle this fault somehow.
        }
        DBG(" end handler");
    }
    DBG(" exit");
    return 0;
}