예제 #1
0
/**
 * Set default hardware params
 */
static int playback_default_hw_params(struct gaudio_snd_dev *snd)
{
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_hw_params *params;
	snd_pcm_sframes_t result;

       /*
	* SNDRV_PCM_ACCESS_RW_INTERLEAVED,
	* SNDRV_PCM_FORMAT_S16_LE
	* CHANNELS: 2
	* RATE: 48000
	*/
	snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
	snd->format = SNDRV_PCM_FORMAT_S16_LE;
	snd->channels = 2;
	snd->rate = 48000;

	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params)
		return -ENOMEM;

	_snd_pcm_hw_params_any(params);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
			snd->access, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
			snd->format, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
			snd->channels, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
			snd->rate, 0);

	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params);

	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
	if (result < 0) {
		ERROR(snd->card,
			"Preparing sound card failed: %d\n", (int)result);
		kfree(params);
		return result;
	}

	/* Store the hardware parameters */
	snd->access = params_access(params);
	snd->format = params_format(params);
	snd->channels = params_channels(params);
	snd->rate = params_rate(params);

	kfree(params);

	INFO(snd->card,
		"Hardware params: access %x, format %x, channels %d, rate %d\n",
		snd->access, snd->format, snd->channels, snd->rate);

	return 0;
}
예제 #2
0
파일: u_uac1.c 프로젝트: Leoyzen/Charm-Eye
static int playback_prepare_params(struct gaudio_snd_dev *snd)
{
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_hw_params *params;
	snd_pcm_sframes_t result;

	snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
	snd->format = SNDRV_PCM_FORMAT_S16_LE;
	snd->channels = 2;
	snd->rate = 8000;

	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params)
		return -ENOMEM;

	_snd_pcm_hw_params_any(params);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
			snd->access, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
			snd->format, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
			snd->channels, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
			snd->rate, 0);

	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
	if (result < 0)
		pr_err("SNDRV_PCM_IOCTL_DROP failed: %d\n", (int)result);

	result = snd_pcm_kernel_ioctl(substream,
			SNDRV_PCM_IOCTL_HW_PARAMS, params);
	if (result < 0) {
		pr_err("SNDRV_PCM_IOCTL_HW_PARAMS failed: %d\n", (int)result);
		kfree(params);
		return result;
	}

	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
	if (result < 0)
		pr_err("Preparing playback failed: %d\n", (int)result);


	
	snd->access = params_access(params);
	snd->format = params_format(params);
	snd->channels = params_channels(params);
	snd->rate = params_rate(params);

	kfree(params);

	pr_debug("playback params: access %x, format %x, channels %d, rate %d\n",
		snd->access, snd->format, snd->channels, snd->rate);

	return 0;
}
예제 #3
0
파일: u_uac1.c 프로젝트: Leoyzen/Charm-Eye
static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
{
	struct gaudio_snd_dev	*snd = &card->playback;
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	mm_segment_t old_fs;
	ssize_t result;
	snd_pcm_sframes_t frames;
	int err = 0;

	if (!count) {
		pr_err("Buffer is empty, no data to play");
		return 0;
	}

	if (!audio_reinit) {
		err = gaudio_open_streams();
		if (err) {
			pr_err("Failed to init audio streams");
			return 0;
		}
		audio_reinit = 1;
	}

try_again:
	if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
		runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ||
		runtime->status->state == SNDRV_PCM_STATE_SETUP) {
		result = snd_pcm_kernel_ioctl(substream,
				SNDRV_PCM_IOCTL_PREPARE, NULL);
		if (result < 0) {
			pr_err("Preparing playback failed: %d\n",
					(int)result);
			return result;
		}
	}

	if (!runtime->frame_bits) {
		pr_err("SND failure - runtime->frame_bits == 0");
		return 0;
	}

	frames = bytes_to_frames(runtime, count);
	pr_debug("runtime->frame_bits = %d, count = %d, frames = %d",
		runtime->frame_bits, (int)count, (int)frames);

	old_fs = get_fs();
	set_fs(KERNEL_DS);
	result = snd_pcm_lib_write(snd->substream, buf, frames);
	if (result != frames) {
		pr_err("snd_pcm_lib_write failed with err %d\n", (int)result);
		set_fs(old_fs);
		goto try_again;
	}
	set_fs(old_fs);

	pr_debug("Done. Sent %d frames", (int)frames);

	return 0;
}
예제 #4
0
int ksnd_pcm_start(ksnd_pcm_t *kpcm)
{
	snd_pcm_substream_t *substream = kpcm->substream;
	if (substream != NULL)
		snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
	return 0;
}
예제 #5
0
/**
 * Playback audio buffer data by ALSA PCM device
 */
static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
{
	struct gaudio_snd_dev	*snd = &card->playback;
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	mm_segment_t old_fs;
	ssize_t result;
	snd_pcm_sframes_t frames;

try_again:
	if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
		runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
		result = snd_pcm_kernel_ioctl(substream,
				SNDRV_PCM_IOCTL_PREPARE, NULL);
		if (result < 0) {
			ERROR(card, "Preparing sound card failed: %d\n",
					(int)result);
			return result;
		}
	}

	frames = bytes_to_frames(runtime, count);
	old_fs = get_fs();
	set_fs(KERNEL_DS);
	result = snd_pcm_lib_write(snd->substream, buf, frames);
	if (result != frames) {
		ERROR(card, "Playback error: %d\n", (int)result);
		set_fs(old_fs);
		goto try_again;
	}
	set_fs(old_fs);

	return 0;
}
예제 #6
0
int ksnd_pcm_prepare(ksnd_pcm_t *kpcm)
{
	int err;
	snd_pcm_substream_t *substream = kpcm->substream;
	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
	if (err < 0)
	{
		snd_printd("alsa_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
		return err;
	}
	return 0;
}
예제 #7
0
int ksnd_pcm_hw_params(ksnd_pcm_t *kpcm, ksnd_pcm_hw_params_t *params)
{
	snd_pcm_substream_t *substream = kpcm->substream;
	int err;
	if (substream == NULL)
		return -EFAULT;
	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS,
							   params);
	if (0 != err)
		return err;
	kpcm->actual_hwparams = *params;
	return 0;
}
예제 #8
0
int ksnd_pcm_delay(ksnd_pcm_t *pcm, snd_pcm_sframes_t *delay)
{
	snd_pcm_substream_t *substream = pcm->substream;
	snd_pcm_sframes_t frames;
	int err;
	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &frames);
	if (err < 0)
	{
		return err;
	}
	*delay = frames;
	return 0;
}
예제 #9
0
파일: u_uac1.c 프로젝트: Leoyzen/Charm-Eye
static size_t u_audio_capture(struct gaudio *card, void *buf, size_t count)
{
	ssize_t result;
	mm_segment_t old_fs;
	snd_pcm_sframes_t frames;
	int err = 0;

	struct gaudio_snd_dev	 *snd = &card->capture;
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_runtime   *runtime = substream->runtime;

	if (!audio_reinit) {
		err = gaudio_open_streams();
		if (err) {
			pr_err("Failed to init audio streams: err %d", err);
			return 0;
		}
		audio_reinit = 1;
	}

try_again:
	if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
		runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ||
		runtime->status->state == SNDRV_PCM_STATE_SETUP) {
		result = snd_pcm_kernel_ioctl(substream,
				SNDRV_PCM_IOCTL_PREPARE, NULL);
		if (result < 0) {
			pr_err("Preparing capture failed: %d\n",
					(int)result);
			return result;
		}
	}

	frames = bytes_to_frames(runtime, count);

	old_fs = get_fs();
	set_fs(KERNEL_DS);

	pr_debug("frames = %d, count = %d", (int)frames, count);

	result = snd_pcm_lib_read(substream, buf, frames);
	if (result != frames) {
		pr_err("Capture error: %d\n", (int)result);
		set_fs(old_fs);
		goto try_again;
	}

	set_fs(old_fs);

	return 0;
}
예제 #10
0
파일: u_uac1.c 프로젝트: Leoyzen/Charm-Eye
static int capture_prepare_params(struct gaudio_snd_dev *snd)
{
	struct snd_pcm_substream *substream = snd->substream;
	struct snd_pcm_runtime   *runtime = substream->runtime;
	struct snd_pcm_hw_params *params;
	struct snd_pcm_sw_params *swparams;
	unsigned long period_size;
	unsigned long buffer_size;
	snd_pcm_sframes_t result = 0;

	snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
	snd->format = SNDRV_PCM_FORMAT_S16_LE;
	snd->channels = 1;
	snd->rate = 8000;

	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params) {
		pr_err("Failed to allocate hw params");
		return -ENOMEM;
	}

	_snd_pcm_hw_params_any(params);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
			snd->access, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
			snd->format, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
			snd->channels, 0);
	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
			snd->rate, 0);

	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
	if (result < 0)
		pr_err("SNDRV_PCM_IOCTL_DROP failed: %d\n", (int)result);

	result = snd_pcm_kernel_ioctl(substream,
			SNDRV_PCM_IOCTL_HW_PARAMS, params);
	if (result < 0) {
		pr_err("SNDRV_PCM_IOCTL_HW_PARAMS failed: %d\n", (int)result);
		kfree(params);
		return result;
	}

	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE,
					NULL);
	if (result < 0)
		pr_err("Preparing capture failed: %d\n", (int)result);

	
	snd->access = params_access(params);
	snd->format = params_format(params);
	snd->channels = params_channels(params);
	snd->rate = params_rate(params);

	runtime->frame_bits = snd_pcm_format_physical_width(runtime->format);

	swparams = kzalloc(sizeof(*swparams), GFP_KERNEL);
	if (!swparams) {
		pr_err("Failed to allocate sw params");
		kfree(params);
		return -ENOMEM;
	}

	buffer_size = pcm_buffer_size(params);
	period_size = pcm_period_size(params);
	swparams->avail_min = period_size/2;
	swparams->xfer_align = period_size/2;

	kfree(params);

	swparams->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
	swparams->period_step = 1;
	swparams->start_threshold = 1;
	swparams->stop_threshold = INT_MAX;
	swparams->silence_size = 0;
	swparams->silence_threshold = 0;

	result = snd_pcm_kernel_ioctl(substream,
			SNDRV_PCM_IOCTL_SW_PARAMS, swparams);
	if (result < 0)
		pr_err("SNDRV_PCM_IOCTL_SW_PARAMS failed: %d\n", (int)result);

	kfree(swparams);

	pr_debug("capture params: access %x, format %x, channels %d, rate %d\n",
		snd->access, snd->format, snd->channels, snd->rate);

	return result;
}
예제 #11
0
int ksnd_pcm_set_params(ksnd_pcm_t *pcm,
						int nrchannels, int sampledepth, int samplerate,
						int periodsize, int buffersize)
{
	snd_pcm_substream_t *substream = pcm->substream;
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_hw_params_t *hw_params = NULL;
	snd_pcm_sw_params_t *sw_params = NULL;
	int err;
	int format;
	snd_mask_t mask;
	int i;
	void *hwbuf;
	err = ksnd_pcm_hw_params_malloc(&hw_params);
	if (0 != err)
		goto failure;
	sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
	if (!sw_params)
	{
		err = -ENOMEM;
		goto failure;
	}
	switch (sampledepth)
	{
		case 16:
			format = SNDRV_PCM_FORMAT_S16_LE;
			break;
		case 24:
			sampledepth = 32;
		/*FALLTHRU*/
		case 32:
			format = SNDRV_PCM_FORMAT_S32_LE;
			break;
		default:
			snd_printd("%s Unsupported sampledepth %d\n",
					   __FUNCTION__, sampledepth);
			err = -EINVAL;
			goto failure;
	}
	err = ksnd_pcm_hw_params_any(pcm, hw_params);
	if (snd_BUG_ON(err < 0))
		goto failure;
	_snd_pcm_hw_param_setinteger(hw_params, SNDRV_PCM_HW_PARAM_PERIODS);
	_snd_pcm_hw_param_min(hw_params, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
	snd_mask_none(&mask);
	snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
	err =
		snd_pcm_hw_param_mask(substream, hw_params,
							  SNDRV_PCM_HW_PARAM_ACCESS, &mask);
	if (err < 0)
	{
		err = -EINVAL;
		goto failure;
	}
	err =
		snd_pcm_hw_param_set(substream, hw_params, SNDRV_PCM_HW_PARAM_RATE,
							 samplerate, 0);
	if (snd_BUG_ON(err < 0))
		goto failure;
	err =
		snd_pcm_hw_param_near(substream, hw_params,
							  SNDRV_PCM_HW_PARAM_CHANNELS, nrchannels,
							  NULL);
	if (snd_BUG_ON(err < 0))
		goto failure;
	err =
		snd_pcm_hw_param_near(substream, hw_params,
							  SNDRV_PCM_HW_PARAM_FORMAT, format, 0);
	if (snd_BUG_ON(err < 0))
		goto failure;
	err =
		snd_pcm_hw_param_near(substream, hw_params,
							  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, periodsize,
							  NULL);
	if (snd_BUG_ON(err < 0))
		goto failure;
	err =
		snd_pcm_hw_param_near(substream, hw_params,
							  SNDRV_PCM_HW_PARAM_BUFFER_SIZE, buffersize,
							  NULL);
	if (snd_BUG_ON(err < 0))
		goto failure;
	_ksnd_pcm_drop(substream);
	/*now we re-use the 61937 control to enable the HW sync mechanism */
	if (0 != (err = ksnd_pcm_hw_params(pcm, hw_params) < 0))
	{
		snd_printd("HW_PARAMS failed: for %d:%d code is %i\n",
				   substream->pcm->card->number, substream->pcm->device,
				   err);
		goto failure;
	}
	memset(sw_params, 0, sizeof(*sw_params));
	sw_params->start_threshold =
		(runtime->buffer_size - (runtime->period_size * 2));
	sw_params->stop_threshold = runtime->buffer_size;
	sw_params->period_step = 1;
	sw_params->sleep_min = 0;
	sw_params->avail_min = runtime->period_size;
	sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
	sw_params->silence_threshold = runtime->period_size;
	sw_params->silence_size = runtime->period_size;
	if ((err =
				snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS,
									 sw_params)) < 0)
	{
		snd_printd("SW_PARAMS failed: for %d:%d code is %i\n",
				   substream->pcm->card->number, substream->pcm->device,
				   err);
		goto failure;
	}
	if ((err = ksnd_pcm_prepare(pcm)) < 0)
		goto failure;
	if (pcm->hwareas[0].addr)
		iounmap(pcm->hwareas[0].addr);
	hwbuf = ioremap_nocache(runtime->dma_addr, runtime->dma_bytes);
	for (i = 0; i < nrchannels; i++)
	{
		pcm->hwareas[i].addr = hwbuf;
		pcm->hwareas[i].first = i * sampledepth;
		pcm->hwareas[i].step = nrchannels * sampledepth;
	}
	nrchannels = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS, 0);
	samplerate = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_RATE, 0);
	periodsize = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 0);
	buffersize = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0);
	printk(KERN_DEBUG "ksound: Set parameters for hw:%d,%d to %d x %dhz with period %d (of %d)\n",
		   substream->pcm->card->number, substream->pcm->device,
		   nrchannels, samplerate, periodsize, buffersize);
	err = 0;
failure:
	if (hw_params)
		ksnd_pcm_hw_params_free(hw_params);
	if (sw_params)
		kfree(sw_params);
	return err;
}
예제 #12
0
static inline int _ksnd_pcm_pause(snd_pcm_substream_t *substream,
								  unsigned int push)
{
	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PAUSE, (void *) push);
	return 0;
}
예제 #13
0
static inline int _ksnd_pcm_drain(snd_pcm_substream_t *substream)
{
	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
	return 0;
}