usb: f_uac2: adds support for SS and SSP
Patch adds support of SS and SSP speed. Signed-off-by: Pawel Laszczak <pawell@cadence.com> Link: https://lore.kernel.org/r/20210310105216.38202-1-pawell@gli-login.cadence.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
fb9b31e4ea
commit
f8cb3d556b
|
@ -284,6 +284,24 @@ static struct usb_endpoint_descriptor hs_epout_desc = {
|
||||||
.bInterval = 4,
|
.bInterval = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_endpoint_descriptor ss_epout_desc = {
|
||||||
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
|
||||||
|
.bEndpointAddress = USB_DIR_OUT,
|
||||||
|
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||||
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
|
.bInterval = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_ss_ep_comp_descriptor ss_epout_desc_comp = {
|
||||||
|
.bLength = sizeof(ss_epout_desc_comp),
|
||||||
|
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||||
|
.bMaxBurst = 0,
|
||||||
|
.bmAttributes = 0,
|
||||||
|
/* wBytesPerInterval = DYNAMIC */
|
||||||
|
};
|
||||||
|
|
||||||
/* CS AS ISO OUT Endpoint */
|
/* CS AS ISO OUT Endpoint */
|
||||||
static struct uac2_iso_endpoint_descriptor as_iso_out_desc = {
|
static struct uac2_iso_endpoint_descriptor as_iso_out_desc = {
|
||||||
.bLength = sizeof as_iso_out_desc,
|
.bLength = sizeof as_iso_out_desc,
|
||||||
|
@ -361,6 +379,24 @@ static struct usb_endpoint_descriptor hs_epin_desc = {
|
||||||
.bInterval = 4,
|
.bInterval = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_endpoint_descriptor ss_epin_desc = {
|
||||||
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
|
||||||
|
.bEndpointAddress = USB_DIR_IN,
|
||||||
|
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||||
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
|
.bInterval = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_ss_ep_comp_descriptor ss_epin_desc_comp = {
|
||||||
|
.bLength = sizeof(ss_epin_desc_comp),
|
||||||
|
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||||
|
.bMaxBurst = 0,
|
||||||
|
.bmAttributes = 0,
|
||||||
|
/* wBytesPerInterval = DYNAMIC */
|
||||||
|
};
|
||||||
|
|
||||||
/* CS AS ISO IN Endpoint */
|
/* CS AS ISO IN Endpoint */
|
||||||
static struct uac2_iso_endpoint_descriptor as_iso_in_desc = {
|
static struct uac2_iso_endpoint_descriptor as_iso_in_desc = {
|
||||||
.bLength = sizeof as_iso_in_desc,
|
.bLength = sizeof as_iso_in_desc,
|
||||||
|
@ -433,6 +469,38 @@ static struct usb_descriptor_header *hs_audio_desc[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_descriptor_header *ss_audio_desc[] = {
|
||||||
|
(struct usb_descriptor_header *)&iad_desc,
|
||||||
|
(struct usb_descriptor_header *)&std_ac_if_desc,
|
||||||
|
|
||||||
|
(struct usb_descriptor_header *)&ac_hdr_desc,
|
||||||
|
(struct usb_descriptor_header *)&in_clk_src_desc,
|
||||||
|
(struct usb_descriptor_header *)&out_clk_src_desc,
|
||||||
|
(struct usb_descriptor_header *)&usb_out_it_desc,
|
||||||
|
(struct usb_descriptor_header *)&io_in_it_desc,
|
||||||
|
(struct usb_descriptor_header *)&usb_in_ot_desc,
|
||||||
|
(struct usb_descriptor_header *)&io_out_ot_desc,
|
||||||
|
|
||||||
|
(struct usb_descriptor_header *)&std_as_out_if0_desc,
|
||||||
|
(struct usb_descriptor_header *)&std_as_out_if1_desc,
|
||||||
|
|
||||||
|
(struct usb_descriptor_header *)&as_out_hdr_desc,
|
||||||
|
(struct usb_descriptor_header *)&as_out_fmt1_desc,
|
||||||
|
(struct usb_descriptor_header *)&ss_epout_desc,
|
||||||
|
(struct usb_descriptor_header *)&ss_epout_desc_comp,
|
||||||
|
(struct usb_descriptor_header *)&as_iso_out_desc,
|
||||||
|
|
||||||
|
(struct usb_descriptor_header *)&std_as_in_if0_desc,
|
||||||
|
(struct usb_descriptor_header *)&std_as_in_if1_desc,
|
||||||
|
|
||||||
|
(struct usb_descriptor_header *)&as_in_hdr_desc,
|
||||||
|
(struct usb_descriptor_header *)&as_in_fmt1_desc,
|
||||||
|
(struct usb_descriptor_header *)&ss_epin_desc,
|
||||||
|
(struct usb_descriptor_header *)&ss_epin_desc_comp,
|
||||||
|
(struct usb_descriptor_header *)&as_iso_in_desc,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct cntrl_cur_lay3 {
|
struct cntrl_cur_lay3 {
|
||||||
__le32 dCUR;
|
__le32 dCUR;
|
||||||
};
|
};
|
||||||
|
@ -459,6 +527,7 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_SPEED_HIGH:
|
case USB_SPEED_HIGH:
|
||||||
|
case USB_SPEED_SUPER:
|
||||||
max_size_ep = 1024;
|
max_size_ep = 1024;
|
||||||
factor = 8000;
|
factor = 8000;
|
||||||
break;
|
break;
|
||||||
|
@ -488,6 +557,72 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
|
||||||
/* Use macro to overcome line length limitation */
|
/* Use macro to overcome line length limitation */
|
||||||
#define USBDHDR(p) (struct usb_descriptor_header *)(p)
|
#define USBDHDR(p) (struct usb_descriptor_header *)(p)
|
||||||
|
|
||||||
|
static void setup_headers(struct f_uac2_opts *opts,
|
||||||
|
struct usb_descriptor_header **headers,
|
||||||
|
enum usb_device_speed speed)
|
||||||
|
{
|
||||||
|
struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL;
|
||||||
|
struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL;
|
||||||
|
struct usb_endpoint_descriptor *epout_desc;
|
||||||
|
struct usb_endpoint_descriptor *epin_desc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (speed) {
|
||||||
|
case USB_SPEED_FULL:
|
||||||
|
epout_desc = &fs_epout_desc;
|
||||||
|
epin_desc = &fs_epin_desc;
|
||||||
|
break;
|
||||||
|
case USB_SPEED_HIGH:
|
||||||
|
epout_desc = &hs_epout_desc;
|
||||||
|
epin_desc = &hs_epin_desc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
epout_desc = &ss_epout_desc;
|
||||||
|
epin_desc = &ss_epin_desc;
|
||||||
|
epout_desc_comp = &ss_epout_desc_comp;
|
||||||
|
epin_desc_comp = &ss_epin_desc_comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
headers[i++] = USBDHDR(&iad_desc);
|
||||||
|
headers[i++] = USBDHDR(&std_ac_if_desc);
|
||||||
|
headers[i++] = USBDHDR(&ac_hdr_desc);
|
||||||
|
if (EPIN_EN(opts))
|
||||||
|
headers[i++] = USBDHDR(&in_clk_src_desc);
|
||||||
|
if (EPOUT_EN(opts)) {
|
||||||
|
headers[i++] = USBDHDR(&out_clk_src_desc);
|
||||||
|
headers[i++] = USBDHDR(&usb_out_it_desc);
|
||||||
|
}
|
||||||
|
if (EPIN_EN(opts)) {
|
||||||
|
headers[i++] = USBDHDR(&io_in_it_desc);
|
||||||
|
headers[i++] = USBDHDR(&usb_in_ot_desc);
|
||||||
|
}
|
||||||
|
if (EPOUT_EN(opts)) {
|
||||||
|
headers[i++] = USBDHDR(&io_out_ot_desc);
|
||||||
|
headers[i++] = USBDHDR(&std_as_out_if0_desc);
|
||||||
|
headers[i++] = USBDHDR(&std_as_out_if1_desc);
|
||||||
|
headers[i++] = USBDHDR(&as_out_hdr_desc);
|
||||||
|
headers[i++] = USBDHDR(&as_out_fmt1_desc);
|
||||||
|
headers[i++] = USBDHDR(epout_desc);
|
||||||
|
if (epout_desc_comp)
|
||||||
|
headers[i++] = USBDHDR(epout_desc_comp);
|
||||||
|
|
||||||
|
headers[i++] = USBDHDR(&as_iso_out_desc);
|
||||||
|
}
|
||||||
|
if (EPIN_EN(opts)) {
|
||||||
|
headers[i++] = USBDHDR(&std_as_in_if0_desc);
|
||||||
|
headers[i++] = USBDHDR(&std_as_in_if1_desc);
|
||||||
|
headers[i++] = USBDHDR(&as_in_hdr_desc);
|
||||||
|
headers[i++] = USBDHDR(&as_in_fmt1_desc);
|
||||||
|
headers[i++] = USBDHDR(epin_desc);
|
||||||
|
if (epin_desc_comp)
|
||||||
|
headers[i++] = USBDHDR(epin_desc_comp);
|
||||||
|
|
||||||
|
headers[i++] = USBDHDR(&as_iso_in_desc);
|
||||||
|
}
|
||||||
|
headers[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void setup_descriptor(struct f_uac2_opts *opts)
|
static void setup_descriptor(struct f_uac2_opts *opts)
|
||||||
{
|
{
|
||||||
/* patch descriptors */
|
/* patch descriptors */
|
||||||
|
@ -537,71 +672,9 @@ static void setup_descriptor(struct f_uac2_opts *opts)
|
||||||
iad_desc.bInterfaceCount++;
|
iad_desc.bInterfaceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
setup_headers(opts, fs_audio_desc, USB_SPEED_FULL);
|
||||||
fs_audio_desc[i++] = USBDHDR(&iad_desc);
|
setup_headers(opts, hs_audio_desc, USB_SPEED_HIGH);
|
||||||
fs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
|
setup_headers(opts, ss_audio_desc, USB_SPEED_SUPER);
|
||||||
fs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
|
|
||||||
if (EPIN_EN(opts))
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
|
|
||||||
if (EPOUT_EN(opts)) {
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
|
|
||||||
}
|
|
||||||
if (EPIN_EN(opts)) {
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
|
|
||||||
}
|
|
||||||
if (EPOUT_EN(opts)) {
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&fs_epout_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
|
|
||||||
}
|
|
||||||
if (EPIN_EN(opts)) {
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&fs_epin_desc);
|
|
||||||
fs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
|
|
||||||
}
|
|
||||||
fs_audio_desc[i] = NULL;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&iad_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
|
|
||||||
if (EPIN_EN(opts))
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
|
|
||||||
if (EPOUT_EN(opts)) {
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
|
|
||||||
}
|
|
||||||
if (EPIN_EN(opts)) {
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
|
|
||||||
}
|
|
||||||
if (EPOUT_EN(opts)) {
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&hs_epout_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
|
|
||||||
}
|
|
||||||
if (EPIN_EN(opts)) {
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&hs_epin_desc);
|
|
||||||
hs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
|
|
||||||
}
|
|
||||||
hs_audio_desc[i] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -716,6 +789,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = set_ep_max_packet_size(uac2_opts, &ss_epin_desc, USB_SPEED_SUPER,
|
||||||
|
true);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_ep_max_packet_size(uac2_opts, &ss_epout_desc, USB_SPEED_SUPER,
|
||||||
|
false);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (EPOUT_EN(uac2_opts)) {
|
if (EPOUT_EN(uac2_opts)) {
|
||||||
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
|
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
|
||||||
if (!agdev->out_ep) {
|
if (!agdev->out_ep) {
|
||||||
|
@ -739,13 +826,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||||
le16_to_cpu(fs_epout_desc.wMaxPacketSize),
|
le16_to_cpu(fs_epout_desc.wMaxPacketSize),
|
||||||
le16_to_cpu(hs_epout_desc.wMaxPacketSize));
|
le16_to_cpu(hs_epout_desc.wMaxPacketSize));
|
||||||
|
|
||||||
|
agdev->in_ep_maxpsize = max_t(u16, agdev->in_ep_maxpsize,
|
||||||
|
le16_to_cpu(ss_epin_desc.wMaxPacketSize));
|
||||||
|
agdev->out_ep_maxpsize = max_t(u16, agdev->out_ep_maxpsize,
|
||||||
|
le16_to_cpu(ss_epout_desc.wMaxPacketSize));
|
||||||
|
|
||||||
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
|
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
|
||||||
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
|
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
|
||||||
|
ss_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
|
||||||
|
ss_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
|
||||||
|
|
||||||
setup_descriptor(uac2_opts);
|
setup_descriptor(uac2_opts);
|
||||||
|
|
||||||
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL,
|
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, ss_audio_desc,
|
||||||
NULL);
|
ss_audio_desc);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue