Skip to content

Commit

Permalink
fixed synchronisation issues by changing work_queue function and redu…
Browse files Browse the repository at this point in the history
…ced latency through smaller buffers

Change-Id: I96fc227d9b38eb2e7a8f3ded68ef027f182624fc
  • Loading branch information
rbrune committed Feb 17, 2015
1 parent 4d46bbf commit ea3c5e5
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 31 deletions.
12 changes: 6 additions & 6 deletions drivers/usb/gadget/f_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
*/
#define F_AUDIO_AC_INTERFACE 0
#define F_AUDIO_AS_INTERFACE 1
#define F_AUDIO_NUM_INTERFACES 2
#define F_AUDIO_NUM_INTERFACES 1

/* B.3.1 Standard AC Interface Descriptor */
static struct usb_interface_descriptor ac_interface_desc __initdata = {
Expand All @@ -54,23 +54,23 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = {
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
};

DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);

#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
/* 1 input terminal, 1 output terminal and 1 feature unit */
#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
+ UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
/* B.3.2 Class-Specific AC Interface Descriptor */
static struct uac1_ac_header_descriptor_2 ac_header_desc = {
static struct uac1_ac_header_descriptor_1 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_LENGTH,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_HEADER,
.bcdADC = __constant_cpu_to_le16(0x0100),
.wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
.bInCollection = F_AUDIO_NUM_INTERFACES,
.baInterfaceNr = {
[0] = F_AUDIO_AC_INTERFACE,
[1] = F_AUDIO_AS_INTERFACE,
[0] = 1,
/*[1] = F_AUDIO_AS_INTERFACE,*/
}
};

Expand Down Expand Up @@ -193,7 +193,7 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = {
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = UAC_EP_GENERAL,
.bmAttributes = 1,
.bLockDelayUnits = 1,
.bLockDelayUnits = 2,
.wLockDelay = __constant_cpu_to_le16(1),
};

Expand Down
66 changes: 42 additions & 24 deletions drivers/usb/gadget/f_uac1.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ static int req_count = 256;
module_param(req_count, int, S_IRUGO);
MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");

/*static int audio_buf_size = 48000; */
static int audio_buf_size = 32000;
static int audio_buf_size = 1440;
//static int audio_buf_size = 2000;
/*static int audio_buf_size = 24000; */
module_param(audio_buf_size, int, S_IRUGO);
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");

Expand Down Expand Up @@ -225,7 +226,7 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = {
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = UAC_EP_GENERAL,
.bmAttributes = 0,
.bLockDelayUnits = 2,
.bLockDelayUnits = 1,
.wLockDelay = __constant_cpu_to_le16(1),
};

Expand Down Expand Up @@ -313,19 +314,21 @@ static void f_audio_playback_work(struct work_struct *data)
struct f_audio *audio = container_of(data, struct f_audio,
playback_work);
struct f_audio_buf *play_buf;

spin_lock_irq(&audio->lock);
if (list_empty(&audio->play_queue)) {
spin_unlock_irq(&audio->lock);
return;
}
play_buf = list_first_entry(&audio->play_queue,
struct f_audio_buf, list);
list_del(&play_buf->list);
spin_unlock_irq(&audio->lock);

u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
f_audio_buffer_free(play_buf);

while (1) {
spin_lock_irq(&audio->lock);
if (list_empty(&audio->play_queue)) {
spin_unlock_irq(&audio->lock);
return;
}
play_buf = list_first_entry(&audio->play_queue,
struct f_audio_buf, list);
list_del(&play_buf->list);
spin_unlock_irq(&audio->lock);

u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
f_audio_buffer_free(play_buf);
}
}

static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
Expand All @@ -337,19 +340,29 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)

if (!copy_buf)
return -EINVAL;



/* Copy buffer is full, add it to the play_queue */
if (audio_buf_size - copy_buf->actual < req->actual) {
if (audio_buf_size - copy_buf->actual < req->actual) {
list_add_tail(&copy_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;
}



memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
copy_buf->actual += req->actual;
audio->copy_buf = copy_buf;

/*
if (audio->copy_buf->actual > 2000) {
u_audio_playback(&audio->card, audio->copy_buf->buf, audio->copy_buf->actual);
audio->copy_buf->actual = 0;
}
*/

err = usb_ep_queue(ep, req, GFP_ATOMIC);
if (err)
Expand Down Expand Up @@ -782,16 +795,21 @@ int __init control_selector_init(struct f_audio *audio)

mute_control.data[UAC__CUR] = 0x00;

volume_control.data[UAC__CUR] = 0x0000;
volume_control.data[UAC__MIN] = 0x8000;
volume_control.data[UAC__MAX] = 0x7FFF;
volume_control.data[UAC__RES] = 0x000A;
//volume_control.data[UAC__CUR] = 0x0000;
//volume_control.data[UAC__MIN] = 0x8000;
//volume_control.data[UAC__MAX] = 0x7FFF;
//volume_control.data[UAC__RES] = 0x000A;


//volume_control.data[UAC__CUR] = (signed short)-14336;
//volume_control.data[UAC__MIN] = (signed short)-16384;
//volume_control.data[UAC__MAX] = (signed short)16384;
//volume_control.data[UAC__RES] = (signed short)1024;

volume_control.data[UAC__CUR] = (signed short)-14336;
volume_control.data[UAC__MIN] = (signed short)-16384;
volume_control.data[UAC__MAX] = (signed short)16384;
volume_control.data[UAC__RES] = (signed short)1024;
volume_control.data[UAC__MAX] = (signed short)3041;
volume_control.data[UAC__RES] = (signed short)259;


return 0;
Expand Down
10 changes: 9 additions & 1 deletion drivers/usb/gadget/u_uac1.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
ssize_t result;
snd_pcm_sframes_t frames;
unsigned char regvol = 0xff;
int retries = 0;

try_again:
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
Expand All @@ -193,6 +194,7 @@ static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
}

/* try volume change*/

if (snd->mute != mute_control.data[UAC__CUR]) {
INFO(snd->card, "mute: 0x%x\n", mute_control.data[UAC__CUR]);
snd->mute = mute_control.data[UAC__CUR];
Expand All @@ -207,14 +209,20 @@ static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
snd_pcm_kernel_ioctl(substream, 0x400141f9, &regvol);
snd->volume = volume_control.data[UAC__CUR];
}



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);
retries += 1;
if (retries > 10){
ERROR(card, "Too many playback retries: %d\n", retries);
return 0;
}
goto try_again;
}
set_fs(old_fs);
Expand Down

0 comments on commit ea3c5e5

Please sign in to comment.