summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function/f_uac2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_uac2.c')
-rw-r--r--drivers/usb/gadget/function/f_uac2.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 969cfe741380..f6a0d3a1311b 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -22,9 +22,6 @@
#include "u_uac2.h"
-/* Keep everyone on toes */
-#define USB_XFERS 2
-
/*
* The driver implements a simple UAC_2 topology.
* USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
@@ -78,7 +75,7 @@ struct uac2_rtd_params {
size_t period_size;
unsigned max_psize;
- struct uac2_req ureq[USB_XFERS];
+ struct uac2_req *ureq;
spinlock_t lock;
};
@@ -269,6 +266,8 @@ static int
uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+ struct audio_dev *agdev = uac2_to_agdev(uac2);
+ struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
struct uac2_rtd_params *prm;
unsigned long flags;
int err = 0;
@@ -300,7 +299,7 @@ uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
/* Clear buffer after Play stops */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
- memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
+ memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number);
return err;
}
@@ -943,6 +942,8 @@ static inline void
free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
{
struct snd_uac2_chip *uac2 = prm->uac2;
+ struct audio_dev *agdev = uac2_to_agdev(uac2);
+ struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
int i;
if (!prm->ep_enabled)
@@ -950,7 +951,7 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
prm->ep_enabled = false;
- for (i = 0; i < USB_XFERS; i++) {
+ for (i = 0; i < uac2_opts->req_number; i++) {
if (prm->ureq[i].req) {
usb_ep_dequeue(ep, prm->ureq[i].req);
usb_ep_free_request(ep, prm->ureq[i].req);
@@ -1095,31 +1096,47 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize;
- prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+ prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ ret = -ENOMEM;
+ goto err_free_descs;
+ }
+ prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
+ ret = -ENOMEM;
goto err_free_descs;
}
prm = &agdev->uac2.p_prm;
prm->max_psize = hs_epin_desc.wMaxPacketSize;
- prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+ prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ ret = -ENOMEM;
+ goto err_free_descs;
+ }
+ prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
- goto err;
+ ret = -ENOMEM;
+ goto err_no_memory;
}
ret = alsa_uac2_init(agdev);
if (ret)
- goto err;
+ goto err_no_memory;
return 0;
-err:
+err_no_memory:
+ kfree(agdev->uac2.p_prm.ureq);
+ kfree(agdev->uac2.c_prm.ureq);
kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf);
err_free_descs:
usb_free_all_descriptors(fn);
- return -EINVAL;
+ return ret;
}
static int
@@ -1127,6 +1144,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = fn->config->cdev;
struct audio_dev *agdev = func_to_agdev(fn);
+ struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
struct snd_uac2_chip *uac2 = &agdev->uac2;
struct usb_gadget *gadget = cdev->gadget;
struct device *dev = &uac2->pdev.dev;
@@ -1157,7 +1175,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
agdev->as_out_alt = alt;
req_len = prm->max_psize;
} else if (intf == agdev->as_in_intf) {
- struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
unsigned int factor, rate;
struct usb_endpoint_descriptor *ep_desc;
@@ -1203,7 +1220,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
prm->ep_enabled = true;
usb_ep_enable(ep);
- for (i = 0; i < USB_XFERS; i++) {
+ for (i = 0; i < opts->req_number; i++) {
if (!prm->ureq[i].req) {
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req == NULL)
@@ -1487,6 +1504,7 @@ UAC2_ATTRIBUTE(p_ssize);
UAC2_ATTRIBUTE(c_chmask);
UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
+UAC2_ATTRIBUTE(req_number);
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
@@ -1495,6 +1513,7 @@ static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_c_chmask,
&f_uac2_opts_attr_c_srate,
&f_uac2_opts_attr_c_ssize,
+ &f_uac2_opts_attr_req_number,
NULL,
};
@@ -1532,6 +1551,7 @@ static struct usb_function_instance *afunc_alloc_inst(void)
opts->c_chmask = UAC2_DEF_CCHMASK;
opts->c_srate = UAC2_DEF_CSRATE;
opts->c_ssize = UAC2_DEF_CSSIZE;
+ opts->req_number = UAC2_DEF_REQ_NUM;
return &opts->func_inst;
}
@@ -1560,6 +1580,7 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
+ kfree(prm->ureq);
usb_free_all_descriptors(f);
}