Merge "sound: usb: Add snapshot of USB QMI SND drivers"
This commit is contained in:
commit
94911c4e71
6 changed files with 3336 additions and 0 deletions
|
|
@ -167,5 +167,14 @@ config SND_BCD2000
|
|||
|
||||
source "sound/usb/line6/Kconfig"
|
||||
|
||||
config SND_USB_AUDIO_QMI
|
||||
tristate "USB Audio QMI Service driver"
|
||||
depends on QCOM_QMI_HELPERS && SND_USB_AUDIO
|
||||
help
|
||||
Starts USB Audio QMI server to communicate with remote entity
|
||||
to perform operations like enable or disable particular audio
|
||||
stream on a connected USB device, subsystem restart and
|
||||
device disconnect.
|
||||
|
||||
endif # SND_USB
|
||||
|
||||
|
|
|
|||
|
|
@ -35,3 +35,7 @@ obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
|
|||
|
||||
obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
|
||||
obj-$(CONFIG_SND_USB_LINE6) += line6/
|
||||
|
||||
CFLAGS_xhci-sec.o := -I$(srctree)/drivers/usb/host
|
||||
snd-usb-audio-qmi-objs := usb_audio_qmi_v01.o usb_audio_qmi_svc.o xhci-sec.o
|
||||
obj-$(CONFIG_SND_USB_AUDIO_QMI) += snd-usb-audio-qmi.o
|
||||
|
|
|
|||
1842
sound/usb/usb_audio_qmi_svc.c
Normal file
1842
sound/usb/usb_audio_qmi_svc.c
Normal file
File diff suppressed because it is too large
Load diff
893
sound/usb/usb_audio_qmi_v01.c
Normal file
893
sound/usb/usb_audio_qmi_v01.c
Normal file
|
|
@ -0,0 +1,893 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#include "usb_audio_qmi_v01.h"
|
||||
|
||||
static struct qmi_elem_info mem_info_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct mem_info_v01, va),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct mem_info_v01, pa),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct mem_info_v01, size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info apps_mem_info_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct apps_mem_info_v01, evt_ring),
|
||||
.ei_array = mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct apps_mem_info_v01, tr_data),
|
||||
.ei_array = mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct apps_mem_info_v01, tr_sync),
|
||||
.ei_array = mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct apps_mem_info_v01, xfer_buff),
|
||||
.ei_array = mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct apps_mem_info_v01, dcba),
|
||||
.ei_array = mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info usb_endpoint_descriptor_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bLength),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bDescriptorType),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bEndpointAddress),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bmAttributes),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
wMaxPacketSize),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bInterval),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bRefresh),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_endpoint_descriptor_v01,
|
||||
bSynchAddress),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info usb_interface_descriptor_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bLength),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bDescriptorType),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bInterfaceNumber),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bAlternateSetting),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bNumEndpoints),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bInterfaceClass),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bInterfaceSubClass),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
bInterfaceProtocol),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct usb_interface_descriptor_v01,
|
||||
iInterface),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info qmi_uaudio_stream_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
enable),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
usb_token),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
audio_format_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
audio_format),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
number_of_ch_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
number_of_ch),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
bit_rate_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
bit_rate),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
xfer_buff_size_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
xfer_buff_size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
service_interval_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_req_msg_v01,
|
||||
service_interval),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info qmi_uaudio_stream_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
status_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum usb_audio_stream_status_enum_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
status),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
internal_status_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
internal_status),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
slot_id_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
slot_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_token_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_token),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_opr_intf_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_interface_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_opr_intf_desc),
|
||||
.ei_array = usb_interface_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_data_ep_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_endpoint_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_data_ep_desc),
|
||||
.ei_array = usb_endpoint_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x16,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_sync_ep_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_endpoint_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x16,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
std_as_sync_ep_desc),
|
||||
.ei_array = usb_endpoint_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x17,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_audio_spec_revision_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x17,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_audio_spec_revision),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x18,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
data_path_delay_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x18,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
data_path_delay),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x19,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_audio_subslot_size_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x19,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
usb_audio_subslot_size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1A,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
xhci_mem_info_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct apps_mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1A,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
xhci_mem_info),
|
||||
.ei_array = apps_mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1B,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
interrupter_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1B,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
interrupter_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1C,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
speed_info_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum usb_audio_device_speed_enum_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1C,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
speed_info),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1D,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
controller_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x1D,
|
||||
.offset = offsetof(
|
||||
struct qmi_uaudio_stream_resp_msg_v01,
|
||||
controller_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info qmi_uaudio_stream_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(
|
||||
enum usb_audio_device_indication_enum_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
dev_event),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
slot_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_token_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_token),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_opr_intf_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_interface_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_opr_intf_desc),
|
||||
.ei_array = usb_interface_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_data_ep_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_endpoint_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_data_ep_desc),
|
||||
.ei_array = usb_endpoint_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_sync_ep_desc_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct usb_endpoint_descriptor_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
std_as_sync_ep_desc),
|
||||
.ei_array = usb_endpoint_descriptor_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_audio_spec_revision_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_audio_spec_revision),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
data_path_delay_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
data_path_delay),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x16,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_audio_subslot_size_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x16,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
usb_audio_subslot_size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x17,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
xhci_mem_info_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct apps_mem_info_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x17,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
xhci_mem_info),
|
||||
.ei_array = apps_mem_info_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x18,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
interrupter_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x18,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
interrupter_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x19,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
controller_num_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x19,
|
||||
.offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01,
|
||||
controller_num),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
163
sound/usb/usb_audio_qmi_v01.h
Normal file
163
sound/usb/usb_audio_qmi_v01.h
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef USB_QMI_V01_H
|
||||
#define USB_QMI_V01_H
|
||||
|
||||
#define UAUDIO_STREAM_SERVICE_ID_V01 0x41D
|
||||
#define UAUDIO_STREAM_SERVICE_VERS_V01 0x01
|
||||
|
||||
#define QMI_UAUDIO_STREAM_RESP_V01 0x0001
|
||||
#define QMI_UAUDIO_STREAM_REQ_V01 0x0001
|
||||
#define QMI_UAUDIO_STREAM_IND_V01 0x0001
|
||||
|
||||
|
||||
struct mem_info_v01 {
|
||||
u64 va;
|
||||
u64 pa;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct apps_mem_info_v01 {
|
||||
struct mem_info_v01 evt_ring;
|
||||
struct mem_info_v01 tr_data;
|
||||
struct mem_info_v01 tr_sync;
|
||||
struct mem_info_v01 xfer_buff;
|
||||
struct mem_info_v01 dcba;
|
||||
};
|
||||
|
||||
struct usb_endpoint_descriptor_v01 {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bEndpointAddress;
|
||||
u8 bmAttributes;
|
||||
u16 wMaxPacketSize;
|
||||
u8 bInterval;
|
||||
u8 bRefresh;
|
||||
u8 bSynchAddress;
|
||||
};
|
||||
|
||||
struct usb_interface_descriptor_v01 {
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bInterfaceNumber;
|
||||
u8 bAlternateSetting;
|
||||
u8 bNumEndpoints;
|
||||
u8 bInterfaceClass;
|
||||
u8 bInterfaceSubClass;
|
||||
u8 bInterfaceProtocol;
|
||||
u8 iInterface;
|
||||
};
|
||||
|
||||
enum usb_audio_stream_status_enum_v01 {
|
||||
USB_AUDIO_STREAM_STATUS_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
USB_AUDIO_STREAM_REQ_SUCCESS_V01 = 0,
|
||||
USB_AUDIO_STREAM_REQ_FAILURE_V01 = 1,
|
||||
USB_AUDIO_STREAM_REQ_FAILURE_NOT_FOUND_V01 = 2,
|
||||
USB_AUDIO_STREAM_REQ_FAILURE_INVALID_PARAM_V01 = 3,
|
||||
USB_AUDIO_STREAM_REQ_FAILURE_MEMALLOC_V01 = 4,
|
||||
USB_AUDIO_STREAM_STATUS_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
enum usb_audio_device_indication_enum_v01 {
|
||||
USB_AUDIO_DEVICE_INDICATION_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
USB_AUDIO_DEV_CONNECT_V01 = 0,
|
||||
USB_AUDIO_DEV_DISCONNECT_V01 = 1,
|
||||
USB_AUDIO_DEV_SUSPEND_V01 = 2,
|
||||
USB_AUDIO_DEV_RESUME_V01 = 3,
|
||||
USB_AUDIO_DEVICE_INDICATION_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
enum usb_audio_device_speed_enum_v01 {
|
||||
USB_AUDIO_DEVICE_SPEED_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
USB_AUDIO_DEVICE_SPEED_INVALID_V01 = 0,
|
||||
USB_AUDIO_DEVICE_SPEED_LOW_V01 = 1,
|
||||
USB_AUDIO_DEVICE_SPEED_FULL_V01 = 2,
|
||||
USB_AUDIO_DEVICE_SPEED_HIGH_V01 = 3,
|
||||
USB_AUDIO_DEVICE_SPEED_SUPER_V01 = 4,
|
||||
USB_AUDIO_DEVICE_SPEED_SUPER_PLUS_V01 = 5,
|
||||
USB_AUDIO_DEVICE_SPEED_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
struct qmi_uaudio_stream_req_msg_v01 {
|
||||
u8 enable;
|
||||
u32 usb_token;
|
||||
u8 audio_format_valid;
|
||||
u32 audio_format;
|
||||
u8 number_of_ch_valid;
|
||||
u32 number_of_ch;
|
||||
u8 bit_rate_valid;
|
||||
u32 bit_rate;
|
||||
u8 xfer_buff_size_valid;
|
||||
u32 xfer_buff_size;
|
||||
u8 service_interval_valid;
|
||||
u32 service_interval;
|
||||
};
|
||||
#define QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN 46
|
||||
extern struct qmi_elem_info qmi_uaudio_stream_req_msg_v01_ei[];
|
||||
|
||||
struct qmi_uaudio_stream_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u8 status_valid;
|
||||
enum usb_audio_stream_status_enum_v01 status;
|
||||
u8 internal_status_valid;
|
||||
u32 internal_status;
|
||||
u8 slot_id_valid;
|
||||
u32 slot_id;
|
||||
u8 usb_token_valid;
|
||||
u32 usb_token;
|
||||
u8 std_as_opr_intf_desc_valid;
|
||||
struct usb_interface_descriptor_v01 std_as_opr_intf_desc;
|
||||
u8 std_as_data_ep_desc_valid;
|
||||
struct usb_endpoint_descriptor_v01 std_as_data_ep_desc;
|
||||
u8 std_as_sync_ep_desc_valid;
|
||||
struct usb_endpoint_descriptor_v01 std_as_sync_ep_desc;
|
||||
u8 usb_audio_spec_revision_valid;
|
||||
u16 usb_audio_spec_revision;
|
||||
u8 data_path_delay_valid;
|
||||
u8 data_path_delay;
|
||||
u8 usb_audio_subslot_size_valid;
|
||||
u8 usb_audio_subslot_size;
|
||||
u8 xhci_mem_info_valid;
|
||||
struct apps_mem_info_v01 xhci_mem_info;
|
||||
u8 interrupter_num_valid;
|
||||
u8 interrupter_num;
|
||||
u8 speed_info_valid;
|
||||
enum usb_audio_device_speed_enum_v01 speed_info;
|
||||
u8 controller_num_valid;
|
||||
u8 controller_num;
|
||||
};
|
||||
#define QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN 202
|
||||
extern struct qmi_elem_info qmi_uaudio_stream_resp_msg_v01_ei[];
|
||||
|
||||
struct qmi_uaudio_stream_ind_msg_v01 {
|
||||
enum usb_audio_device_indication_enum_v01 dev_event;
|
||||
u32 slot_id;
|
||||
u8 usb_token_valid;
|
||||
u32 usb_token;
|
||||
u8 std_as_opr_intf_desc_valid;
|
||||
struct usb_interface_descriptor_v01 std_as_opr_intf_desc;
|
||||
u8 std_as_data_ep_desc_valid;
|
||||
struct usb_endpoint_descriptor_v01 std_as_data_ep_desc;
|
||||
u8 std_as_sync_ep_desc_valid;
|
||||
struct usb_endpoint_descriptor_v01 std_as_sync_ep_desc;
|
||||
u8 usb_audio_spec_revision_valid;
|
||||
u16 usb_audio_spec_revision;
|
||||
u8 data_path_delay_valid;
|
||||
u8 data_path_delay;
|
||||
u8 usb_audio_subslot_size_valid;
|
||||
u8 usb_audio_subslot_size;
|
||||
u8 xhci_mem_info_valid;
|
||||
struct apps_mem_info_v01 xhci_mem_info;
|
||||
u8 interrupter_num_valid;
|
||||
u8 interrupter_num;
|
||||
u8 controller_num_valid;
|
||||
u8 controller_num;
|
||||
};
|
||||
#define QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN 181
|
||||
extern struct qmi_elem_info qmi_uaudio_stream_ind_msg_v01_ei[];
|
||||
|
||||
#endif
|
||||
425
sound/usb/xhci-sec.c
Normal file
425
sound/usb/xhci-sec.c
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* xHCI secondary ring APIs
|
||||
*
|
||||
* Copyright (c) 2019,2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2008 Intel Corp.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmapool.h>
|
||||
|
||||
#include "xhci.h"
|
||||
|
||||
struct xhci_sec {
|
||||
struct xhci_ring *event_ring;
|
||||
struct xhci_erst erst;
|
||||
/* secondary interrupter */
|
||||
struct xhci_intr_reg __iomem *ir_set;
|
||||
struct xhci_hcd *xhci;
|
||||
int intr_num;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static LIST_HEAD(xhci_sec);
|
||||
|
||||
/* simplified redefinition from XHCI */
|
||||
#define hcd_to_xhci(h) \
|
||||
((struct xhci_hcd *)(((h)->primary_hcd ?: (h))->hcd_priv))
|
||||
|
||||
static int xhci_event_ring_setup(struct xhci_hcd *xhci, struct xhci_ring **er,
|
||||
struct xhci_intr_reg __iomem *ir_set, struct xhci_erst *erst,
|
||||
unsigned int intr_num, gfp_t flags)
|
||||
{
|
||||
dma_addr_t deq;
|
||||
u64 val_64;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
*er = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT, 0, flags);
|
||||
if (!*er)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = xhci_alloc_erst(xhci, *er, erst, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
xhci_dbg(xhci, "intr# %d: num segs = %i, virt addr = %pK, dma addr = 0x%llx",
|
||||
intr_num,
|
||||
erst->num_entries,
|
||||
erst->entries,
|
||||
(unsigned long long)erst->erst_dma_addr);
|
||||
|
||||
/* set ERST count with the number of entries in the segment table */
|
||||
val = readl_relaxed(&ir_set->erst_size);
|
||||
val &= ERST_SIZE_MASK;
|
||||
val |= ERST_NUM_SEGS;
|
||||
xhci_dbg(xhci, "Write ERST size = %i to ir_set %d (some bits preserved)",
|
||||
val, intr_num);
|
||||
writel_relaxed(val, &ir_set->erst_size);
|
||||
|
||||
xhci_dbg(xhci, "intr# %d: Set ERST entries to point to event ring.",
|
||||
intr_num);
|
||||
/* set the segment table base address */
|
||||
xhci_dbg(xhci, "Set ERST base address for ir_set %d = 0x%llx",
|
||||
intr_num,
|
||||
(unsigned long long)erst->erst_dma_addr);
|
||||
val_64 = xhci_read_64(xhci, &ir_set->erst_base);
|
||||
val_64 &= ERST_PTR_MASK;
|
||||
val_64 |= (erst->erst_dma_addr & (u64) ~ERST_PTR_MASK);
|
||||
xhci_write_64(xhci, val_64, &ir_set->erst_base);
|
||||
|
||||
/* Set the event ring dequeue address */
|
||||
deq = xhci_trb_virt_to_dma((*er)->deq_seg, (*er)->dequeue);
|
||||
if (deq == 0 && !in_interrupt())
|
||||
xhci_warn(xhci,
|
||||
"intr# %d:WARN something wrong with SW event ring deq ptr.\n",
|
||||
intr_num);
|
||||
/* Update HC event ring dequeue pointer */
|
||||
val_64 = xhci_read_64(xhci, &ir_set->erst_dequeue);
|
||||
val_64 &= ERST_PTR_MASK;
|
||||
/* Don't clear the EHB bit (which is RW1C) because
|
||||
* there might be more events to service.
|
||||
*/
|
||||
val_64 &= ~ERST_EHB;
|
||||
xhci_dbg(xhci, "intr# %d:Write event ring dequeue pointer, preserving EHB bit",
|
||||
intr_num);
|
||||
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | val_64,
|
||||
&ir_set->erst_dequeue);
|
||||
xhci_dbg(xhci, "Wrote ERST address to ir_set %d.", intr_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct xhci_ring *xhci_sec_event_ring_setup(struct usb_device *udev, unsigned int intr_num)
|
||||
{
|
||||
int ret;
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct xhci_sec *sec;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if (!xhci->max_interrupters)
|
||||
xhci->max_interrupters = HCS_MAX_INTRS(xhci->hcs_params1);
|
||||
|
||||
if ((xhci->xhc_state & XHCI_STATE_HALTED) ||
|
||||
intr_num >= xhci->max_interrupters) {
|
||||
xhci_err(xhci, "%s:state %x intr# %d\n", __func__,
|
||||
xhci->xhc_state, intr_num);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
list_for_each_entry(sec, &xhci_sec, list) {
|
||||
if (sec->xhci == xhci && sec->intr_num == intr_num)
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec = kzalloc(sizeof(*sec), GFP_KERNEL);
|
||||
if (!sec)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
sec->intr_num = intr_num;
|
||||
sec->xhci = xhci;
|
||||
sec->ir_set = &xhci->run_regs->ir_set[intr_num];
|
||||
ret = xhci_event_ring_setup(xhci, &sec->event_ring, sec->ir_set,
|
||||
&sec->erst, intr_num, GFP_KERNEL);
|
||||
if (ret) {
|
||||
xhci_err(xhci, "sec event ring setup failed inter#%d\n",
|
||||
intr_num);
|
||||
kfree(sec);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
list_add_tail(&sec->list, &xhci_sec);
|
||||
done:
|
||||
return sec->event_ring;
|
||||
}
|
||||
|
||||
static void xhci_handle_sec_intr_events(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ring, struct xhci_intr_reg __iomem *ir_set)
|
||||
{
|
||||
union xhci_trb *erdp_trb, *current_trb;
|
||||
struct xhci_segment *seg;
|
||||
u64 erdp_reg;
|
||||
u32 iman_reg;
|
||||
dma_addr_t deq;
|
||||
unsigned long segment_offset;
|
||||
|
||||
/* disable irq, ack pending interrupt and ack all pending events */
|
||||
|
||||
iman_reg = readl_relaxed(&ir_set->irq_pending);
|
||||
iman_reg &= ~IMAN_IE;
|
||||
writel_relaxed(iman_reg, &ir_set->irq_pending);
|
||||
iman_reg = readl_relaxed(&ir_set->irq_pending);
|
||||
if (iman_reg & IMAN_IP)
|
||||
writel_relaxed(iman_reg, &ir_set->irq_pending);
|
||||
|
||||
/* last acked event trb is in erdp reg */
|
||||
erdp_reg = xhci_read_64(xhci, &ir_set->erst_dequeue);
|
||||
deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK);
|
||||
if (!deq) {
|
||||
pr_debug("%s: event ring handling not required\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
seg = ring->first_seg;
|
||||
segment_offset = deq - seg->dma;
|
||||
|
||||
/* find out virtual address of the last acked event trb */
|
||||
erdp_trb = current_trb = &seg->trbs[0] +
|
||||
(segment_offset/sizeof(*current_trb));
|
||||
|
||||
/* read cycle state of the last acked trb to find out CCS */
|
||||
ring->cycle_state = le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE;
|
||||
|
||||
while (1) {
|
||||
/* last trb of the event ring: toggle cycle state */
|
||||
if (current_trb == &seg->trbs[TRBS_PER_SEGMENT - 1]) {
|
||||
ring->cycle_state ^= 1;
|
||||
current_trb = &seg->trbs[0];
|
||||
} else {
|
||||
current_trb++;
|
||||
}
|
||||
|
||||
/* cycle state transition */
|
||||
if ((le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE) !=
|
||||
ring->cycle_state)
|
||||
break;
|
||||
}
|
||||
|
||||
if (erdp_trb != current_trb) {
|
||||
deq = xhci_trb_virt_to_dma(ring->deq_seg, current_trb);
|
||||
if (deq == 0)
|
||||
xhci_warn(xhci,
|
||||
"WARN invalid SW event ring dequeue ptr.\n");
|
||||
/* Update HC event ring dequeue pointer */
|
||||
erdp_reg &= ERST_PTR_MASK;
|
||||
erdp_reg |= ((u64) deq & (u64) ~ERST_PTR_MASK);
|
||||
}
|
||||
|
||||
/* Clear the event handler busy flag (RW1C); event ring is empty. */
|
||||
erdp_reg |= ERST_EHB;
|
||||
xhci_write_64(xhci, erdp_reg, &ir_set->erst_dequeue);
|
||||
}
|
||||
|
||||
static int sec_event_ring_cleanup(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
||||
struct xhci_intr_reg __iomem *ir_set, struct xhci_erst *erst)
|
||||
{
|
||||
int size;
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
|
||||
|
||||
if (!HCD_RH_RUNNING(xhci_to_hcd(xhci)))
|
||||
return 0;
|
||||
|
||||
size = sizeof(struct xhci_erst_entry)*(erst->num_entries);
|
||||
if (erst->entries) {
|
||||
xhci_handle_sec_intr_events(xhci, ring, ir_set);
|
||||
dma_free_coherent(dev, size, erst->entries,
|
||||
erst->erst_dma_addr);
|
||||
erst->entries = NULL;
|
||||
}
|
||||
|
||||
xhci_ring_free(xhci, ring);
|
||||
xhci_dbg(xhci, "Freed sec event ring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xhci_sec_event_ring_cleanup(struct usb_device *udev, struct xhci_ring *ring)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct xhci_sec *sec;
|
||||
|
||||
list_for_each_entry(sec, &xhci_sec, list) {
|
||||
if (sec->event_ring == ring) {
|
||||
sec_event_ring_cleanup(xhci, ring, sec->ir_set,
|
||||
&sec->erst);
|
||||
list_del(&sec->list);
|
||||
kfree(sec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_device *udev,
|
||||
struct xhci_ring *ring, dma_addr_t *dma)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct device *dev = hcd->self.sysdev;
|
||||
struct sg_table sgt;
|
||||
phys_addr_t pa;
|
||||
struct xhci_sec *sec;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd) ||
|
||||
(xhci->xhc_state & XHCI_STATE_HALTED))
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(sec, &xhci_sec, list) {
|
||||
if (sec->event_ring == ring) {
|
||||
dma_get_sgtable(dev, &sgt, ring->first_seg->trbs,
|
||||
ring->first_seg->dma, TRB_SEGMENT_SIZE);
|
||||
|
||||
*dma = ring->first_seg->dma;
|
||||
|
||||
pa = page_to_phys(sg_page(sgt.sgl));
|
||||
sg_free_table(&sgt);
|
||||
|
||||
return pa;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 1 if the arguments are OK;
|
||||
* returns 0 this is a root hub; returns -EINVAL for NULL pointers.
|
||||
*/
|
||||
static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev,
|
||||
const char *func)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
|
||||
if (!hcd || (check_ep && !ep) || !udev) {
|
||||
pr_debug("xHCI %s called with invalid args\n", func);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!udev->parent) {
|
||||
pr_debug("xHCI %s called for root hub\n", func);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
if (check_virt_dev) {
|
||||
if (!udev->slot_id || !xhci->devs[udev->slot_id]) {
|
||||
xhci_dbg(xhci, "xHCI %s called with unaddressed device\n",
|
||||
func);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
if (virt_dev->udev != udev) {
|
||||
xhci_dbg(xhci, "xHCI %s called with udev and virt_dev does not match\n",
|
||||
func);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (xhci->xhc_state & XHCI_STATE_HALTED)
|
||||
return -ENODEV;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma)
|
||||
{
|
||||
int ret;
|
||||
unsigned int ep_index;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct device *dev = hcd->self.sysdev;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct sg_table sgt;
|
||||
phys_addr_t pa;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd))
|
||||
return 0;
|
||||
|
||||
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
|
||||
if (ret <= 0) {
|
||||
xhci_err(xhci, "%s: invalid args\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
|
||||
if (virt_dev->eps[ep_index].ring &&
|
||||
virt_dev->eps[ep_index].ring->first_seg) {
|
||||
|
||||
dma_get_sgtable(dev, &sgt,
|
||||
virt_dev->eps[ep_index].ring->first_seg->trbs,
|
||||
virt_dev->eps[ep_index].ring->first_seg->dma,
|
||||
TRB_SEGMENT_SIZE);
|
||||
|
||||
*dma = virt_dev->eps[ep_index].ring->first_seg->dma;
|
||||
|
||||
pa = page_to_phys(sg_page(sgt.sgl));
|
||||
sg_free_table(&sgt);
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ring the host controller doorbell after placing a command on the ring */
|
||||
int xhci_stop_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
unsigned int ep_index;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_command *cmd;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
cmd = xhci_alloc_command(xhci, true, GFP_NOIO);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
if (!virt_dev) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
if (virt_dev->eps[ep_index].ring &&
|
||||
virt_dev->eps[ep_index].ring->dequeue) {
|
||||
ret = xhci_queue_stop_endpoint(xhci, cmd, udev->slot_id,
|
||||
ep_index, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
xhci_ring_cmd_db(xhci);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
/* Wait for stop endpoint command to finish */
|
||||
wait_for_completion(cmd->completion);
|
||||
|
||||
if (cmd->status == COMP_COMMAND_ABORTED ||
|
||||
cmd->status == COMP_STOPPED) {
|
||||
xhci_warn(xhci,
|
||||
"stop endpoint command timeout for ep%d%s\n",
|
||||
usb_endpoint_num(&ep->desc),
|
||||
usb_endpoint_dir_in(&ep->desc) ? "in" : "out");
|
||||
ret = -ETIME;
|
||||
}
|
||||
goto free_cmd;
|
||||
}
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
free_cmd:
|
||||
xhci_free_command(xhci, cmd);
|
||||
return ret;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue