Exemplo n.º 1
0
static void transfer_done_callback(unsigned long param)
{
    int result;
    struct ksnd_pcm_streaming *streaming = (struct ksnd_pcm_streaming *)param;
    snd_pcm_sframes_t commited_frames;

    BUG_ON(streaming->magic != magic_good);
    BUG_ON(test_bit(FLAG_BUSY, &streaming->flags) != 1);

    // Check if the transfer wasn't stopped by any chance...

    if (test_bit(FLAG_STOPPED, &streaming->flags))
        return;

    // "Commit" playback data

    commited_frames = ksnd_pcm_mmap_commit(streaming->playback_handle,
                                           streaming->playback_offset, streaming->playback_frames);
    if (commited_frames < 0 ||
            (snd_pcm_uframes_t)commited_frames != streaming->playback_frames) {
        ERROR("Playback XRUN!\n");
        result = ksnd_pcm_prepare(streaming->playback_handle);
        if (result != 0) {
            ERROR("Can't recover from playback XRUN!\n");
            return;
        }
    }

    // "Commit" captured data

    commited_frames = ksnd_pcm_mmap_commit(streaming->capture_handle,
                                           streaming->capture_offset, streaming->playback_frames);
    if (commited_frames < 0 ||
            (snd_pcm_uframes_t)commited_frames != streaming->playback_frames) {
        ERROR("Capture XRUN!\n");
        result = ksnd_pcm_prepare(streaming->capture_handle);
        if (result != 0) {
            ERROR("Can't recover from capture XRUN!\n");
            return;
        }
        ksnd_pcm_start(streaming->capture_handle);
    }

    // Release the lock

    clear_bit(FLAG_BUSY, &streaming->flags);

    // If another data period has been received in meantime, trigger it not
    // (period_captured_callback could be skipped because of transfer	in progress)

    if (ksnd_pcm_avail_update(streaming->capture_handle) >=
            streaming->capture_handle->substream->runtime->period_size)
        period_captured_callback(streaming->capture_handle->substream);
}
Exemplo n.º 2
0
int ksnd_pcm_mute(ksnd_pcm_t *kpcm, unsigned int push)
{
	int err;
	snd_pcm_substream_t *substream = kpcm->substream;
	if (push == 0)
	{
		err = ksnd_pcm_prepare(kpcm);
		if (err < 0)
			return err;
		ksnd_pcm_start(kpcm);
	}
	else
	{
		_ksnd_pcm_pause(substream, push);
		_ksnd_pcm_drop(substream);
	}
	return 0;
}
Exemplo n.º 3
0
int ksnd_pcm_streaming_start(ksnd_pcm_streaming_t *handle,
                             ksnd_pcm_t *capture, ksnd_pcm_t *playback)
{
    int result;
    struct ksnd_pcm_streaming *streaming;
    const char *fdmac_id[] = { STM_DMAC_ID, NULL };
    const char *lb_cap[] = { STM_DMA_CAP_LOW_BW, NULL };
    const char *hb_cap[] = { STM_DMA_CAP_HIGH_BW, NULL };

    // Allocate and clean streaming structure

    streaming = kzalloc(sizeof(*streaming), GFP_KERNEL);
    if (streaming == NULL) {
        ERROR("Can't get memory for streaming structure!\n");
        return -ENOMEM;
    }

    // Prepare description

    streaming->capture_handle = capture;
    streaming->playback_handle = playback;
    streaming->magic = magic_good;

    // Initialize FDMA

    streaming->fdma_channel = request_dma_bycap(fdmac_id, lb_cap, "KSOUND_STREAMING");
    if (streaming->fdma_channel < 0) {
        streaming->fdma_channel = request_dma_bycap(fdmac_id, hb_cap, "KSOUND_STREAMING");
        if (streaming->fdma_channel < 0) {
            ERROR("Can't allocate FDMA channel!\n");
            kfree(streaming);
            return -EBUSY;
        }
    }

    dma_params_init(&streaming->fdma_params, MODE_FREERUNNING, STM_DMA_LIST_OPEN);

    dma_params_comp_cb(&streaming->fdma_params, transfer_done_callback,
                       (unsigned long)streaming, STM_DMA_CB_CONTEXT_TASKLET);

    dma_params_err_cb(&streaming->fdma_params, transfer_error_callback,
                      (unsigned long)streaming, STM_DMA_CB_CONTEXT_TASKLET);

    dma_params_DIM_1_x_1(&streaming->fdma_params);

    result = dma_compile_list(streaming->fdma_channel, &streaming->fdma_params, GFP_KERNEL);
    if (result < 0) {
        ERROR("Can't compile FDMA parameters!\n");
        free_dma(streaming->fdma_channel);
        kfree(streaming);
        return -EFAULT;
    }

    // Initialize ALSA

    capture->substream->runtime->transfer_ack_end = period_captured_callback;
    BUG_ON(capture->substream->runtime->private_data != NULL);  // It used to be not used ;-)
    capture->substream->runtime->private_data = streaming;

    ksnd_pcm_start(capture);

    // Return handle

    *handle = streaming;

    return 0;
}