module_param(audio_buf_size, int, S_IRUGO);
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
+/* The first usb audio buf to alsa playback */
+static int first_audio_buf_size = 65500;
+module_param(first_audio_buf_size, int, S_IRUGO);
+MODULE_PARM_DESC(first_audio_buf_size, "First Audio buffer size");
+
static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
+/* Flag to use buffer with first_audio_buf_size to asla */
+static int first_copy_audio_buffer = 1;
/*
* DESCRIPTORS ... most are static, but strings and full
* configuration descriptors are built on demand.
if (!copy_buf)
return -EINVAL;
+ if (!first_copy_audio_buffer) {
/* Copy buffer is full, add it to the play_queue */
- if (audio_buf_size - copy_buf->actual < req->actual) {
- list_add_tail(©_buf->list, &audio->play_queue);
- schedule_work(&audio->playback_work);
- copy_buf = f_audio_buffer_alloc(audio_buf_size);
- if (IS_ERR(copy_buf))
- return -ENOMEM;
+ if (audio_buf_size - copy_buf->actual < req->actual) {
+ list_add_tail(©_buf->list, &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ copy_buf = f_audio_buffer_alloc(audio_buf_size);
+
+ if (IS_ERR(copy_buf))
+ return -ENOMEM;
+ }
+ } else {
+ if (first_audio_buf_size - copy_buf->actual < req->actual) {
+ list_add_tail(©_buf->list, &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ copy_buf = f_audio_buffer_alloc(audio_buf_size);
+
+ if (IS_ERR(copy_buf))
+ return -ENOMEM;
+
+ first_copy_audio_buffer = 0;
+ }
}
memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
if (alt == 1) {
usb_ep_enable(out_ep, audio->out_desc);
out_ep->driver_data = audio;
- audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ audio->copy_buf = f_audio_buffer_alloc(first_audio_buf_size);
if (IS_ERR(audio->copy_buf))
return -ENOMEM;
&audio->play_queue);
schedule_work(&audio->playback_work);
}
+ first_copy_audio_buffer = 1;
}
}
module_param(fn_cntl, charp, S_IRUGO);
MODULE_PARM_DESC(fn_cntl, "Control device file name");
+static int audio_sample_rate = 48000;
+module_param(audio_sample_rate, int, S_IRUGO);
+MODULE_PARM_DESC(audio_sample_rate, "Audio Sample Rate");
+
/*-------------------------------------------------------------------------*/
/**
snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
snd->format = SNDRV_PCM_FORMAT_S16_LE;
snd->channels = 2;
- snd->rate = 48000;
+ if (audio_sample_rate == 44100)
+ snd->rate = 44100;
+ else if (audio_sample_rate == 48000)
+ snd->rate = 48000;
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
_snd_pcm_hw_params_any(params);
+
+ if (audio_sample_rate == 44100) {
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, \
+ 2*1024, 0);
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, \
+ 16*1024, 0);
+ }
_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,
set_fs(KERNEL_DS);
result = snd_pcm_lib_write(snd->substream, buf, frames);
if (result != frames) {
+ msleep_interruptible(2);
ERROR(card, "Playback error: %d\n", (int)result);
set_fs(old_fs);
goto try_again;