From patchwork Thu Jan 16 23:27:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858136 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F235A236A87; Thu, 16 Jan 2025 23:29:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; cv=none; b=TGeSOT0/bbL1ztNR6+Ore1+Z0jUpKmScK2dtEet5DumRB8tUYtSi3J0Bd6l3oXyKIV5PYL1OE1oHApYw0591QXKwnrtYE2tZjAfuH/E6UL0aLPZdJr5vzj4DdeC8GD0Jh0TUrlpebLjasWMB8bkUaxT4BFL4dHtuge9as9xZKyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; c=relaxed/simple; bh=VY0qqb1f0D1wjOTLrZ0tj69RM706ZOFko3EfeR/Ywlw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HPYC1Ip3O+R77cU/otma4d0DkJ6YN202kICGTm4Z3BZ6h0uzC6sbX3kTspZIBugcUbzLqGEVRfodgFTuQ0ss2DlkHsNYNryVHrantjsw3Wl5rlagDlIzR/PS9f07UF25ieA23viyl0fY29ZO+H8dB2oVjbSzzNrWe1bHTJaOFkQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=Nk8CgueH; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="Nk8CgueH" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN7gEF011119; Thu, 16 Jan 2025 23:28:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= zE/y1UAOhCJ31jF00rXMwAFsSRgMWUz68/3SAFHGF/w=; b=Nk8CgueHNKgO70O1 /RgcKDwhu4sgq9plAmeKe0pZ+CDVSBa768T+WInozMA7aeS9bBZU6vbTAoJsAH6r 5SIAJODtmLhxGqGhvJvq2MlZFRFkJduFkYf+lKhg5MXvbZJ8LIBkK2pxVX+7rh5w JnZ05Kq/VykPXRCZVDZjqwbIFi7NSxZPr/jVQBJNyeLGG98u83mZ8Fa2LEEZuyI5 6W0oh/HMRJkT152+/Teyvu2gTCTreo1bzOm/qo16jKlAjim9g08jNHvesXDBcC/8 tafutCHwW626DB4nfXzIoE4W258/8wEWBoRMg84n8YJMZbbVyaovwgcZtkGSTRbH PLKHLw== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:42 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSf8i031813 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:41 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:41 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Mathias Nyman , Wesley Cheng Subject: [PATCH v33 01/31] xhci: sideband: add initial api to register a secondary interrupter entity Date: Thu, 16 Jan 2025 15:27:54 -0800 Message-ID: <20250116232824.3748438-2-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: JpYGoc7cb2qhkdOIZcYPgzSUtLnWM0aQ X-Proofpoint-ORIG-GUID: JpYGoc7cb2qhkdOIZcYPgzSUtLnWM0aQ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 From: Mathias Nyman Introduce XHCI sideband, which manages the USB endpoints being requested by a client driver. This is used for when client drivers are attempting to offload USB endpoints to another entity for handling USB transfers. XHCI sec intr will allow for drivers to fetch the required information about the transfer ring, so the user can submit transfers independently. Expose the required APIs for drivers to register and request for a USB endpoint and to manage XHCI secondary interrupters. Driver renaming, multiple ring segment page linking, proper endpoint clean up, and allowing module compilation added by Wesley Cheng to complete original concept code by Mathias Nyman. Signed-off-by: Mathias Nyman Co-developed-by: Wesley Cheng Signed-off-by: Wesley Cheng --- drivers/usb/host/Kconfig | 9 + drivers/usb/host/Makefile | 2 + drivers/usb/host/xhci-sideband.c | 429 ++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 4 + include/linux/usb/xhci-sideband.h | 73 +++++ 5 files changed, 517 insertions(+) create mode 100644 drivers/usb/host/xhci-sideband.c create mode 100644 include/linux/usb/xhci-sideband.h diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d011d6c753ed..6b9872f16a0b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -104,6 +104,15 @@ config USB_XHCI_RZV2M Say 'Y' to enable the support for the xHCI host controller found in Renesas RZ/V2M SoC. +config USB_XHCI_SIDEBAND + tristate "xHCI support for sideband" + help + Say 'Y' to enable the support for the xHCI sideband capability. + Provide a mechanism for a sideband datapath for payload associated + with audio class endpoints. This allows for an audio DSP to use + xHCI USB endpoints directly, allowing CPU to sleep while playing + audio. + config USB_XHCI_TEGRA tristate "xHCI support for NVIDIA Tegra SoCs" depends on PHY_TEGRA_XUSB diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index be4e5245c52f..435a1e93b40b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -32,6 +32,8 @@ endif xhci-rcar-hcd-y += xhci-rcar.o xhci-rcar-hcd-$(CONFIG_USB_XHCI_RZV2M) += xhci-rzv2m.o +obj-$(CONFIG_USB_XHCI_SIDEBAND) += xhci-sideband.o + obj-$(CONFIG_USB_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c new file mode 100644 index 000000000000..19c58ae60414 --- /dev/null +++ b/drivers/usb/host/xhci-sideband.c @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * xHCI host controller sideband support + * + * Copyright (c) 2023-2025, Intel Corporation. + * + * Author: Mathias Nyman + */ + +#include +#include + +#include "xhci.h" + +/* sideband internal helpers */ +static struct sg_table * +xhci_ring_to_sgtable(struct xhci_sideband *sb, struct xhci_ring *ring) +{ + struct xhci_segment *seg; + struct sg_table *sgt; + unsigned int n_pages; + struct page **pages; + struct device *dev; + size_t sz; + int i; + + dev = xhci_to_hcd(sb->xhci)->self.sysdev; + sz = ring->num_segs * TRB_SEGMENT_SIZE; + n_pages = PAGE_ALIGN(sz) >> PAGE_SHIFT; + pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + kvfree(pages); + return NULL; + } + + seg = ring->first_seg; + if (!seg) + goto err; + /* + * Rings can potentially have multiple segments, create an array that + * carries page references to allocated segments. Utilize the + * sg_alloc_table_from_pages() to create the sg table, and to ensure + * that page links are created. + */ + for (i = 0; i < ring->num_segs; i++) { + dma_get_sgtable(dev, sgt, seg->trbs, seg->dma, + TRB_SEGMENT_SIZE); + pages[i] = sg_page(sgt->sgl); + sg_free_table(sgt); + seg = seg->next; + } + + if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL)) + goto err; + + /* + * Save first segment dma address to sg dma_address field for the sideband + * client to have access to the IOVA of the ring. + */ + sg_dma_address(sgt->sgl) = ring->first_seg->dma; + + return sgt; + +err: + kvfree(pages); + kfree(sgt); + + return NULL; +} + +static void +__xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *ep) +{ + /* + * Issue a stop endpoint command when an endpoint is removed. + * The stop ep cmd handler will handle the ring cleanup. + */ + xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL); + + ep->sideband = NULL; + sb->eps[ep->ep_index] = NULL; +} + +/* sideband api functions */ + +/** + * xhci_sideband_add_endpoint - add endpoint to sideband access list + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Adds an endpoint to the list of sideband accessed endpoints for this usb + * device. + * After an endpoint is added the sideband client can get the endpoint transfer + * ring buffer by calling xhci_sideband_endpoint_buffer() + * + * Return: 0 on success, negative error otherwise. + */ +int +xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + mutex_lock(&sb->mutex); + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &sb->vdev->eps[ep_index]; + + if (ep->ep_state & EP_HAS_STREAMS) { + mutex_unlock(&sb->mutex); + return -EINVAL; + } + + /* + * Note, we don't know the DMA mask of the audio DSP device, if its + * smaller than for xhci it won't be able to access the endpoint ring + * buffer. This could be solved by not allowing the audio class driver + * to add the endpoint the normal way, but instead offload it immediately, + * and let this function add the endpoint and allocate the ring buffer + * with the smallest common DMA mask + */ + if (sb->eps[ep_index] || ep->sideband) { + mutex_unlock(&sb->mutex); + return -EBUSY; + } + + ep->sideband = sb; + sb->eps[ep_index] = ep; + mutex_unlock(&sb->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_sideband_add_endpoint); + +/** + * xhci_sideband_remove_endpoint - remove endpoint from sideband access list + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Removes an endpoint from the list of sideband accessed endpoints for this usb + * device. + * sideband client should no longer touch the endpoint transfer buffer after + * calling this. + * + * Return: 0 on success, negative error otherwise. + */ +int +xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + mutex_lock(&sb->mutex); + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = sb->eps[ep_index]; + + if (!ep || !ep->sideband || ep->sideband != sb) { + mutex_unlock(&sb->mutex); + return -ENODEV; + } + + __xhci_sideband_remove_endpoint(sb, ep); + xhci_initialize_ring_info(ep->ring); + mutex_unlock(&sb->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_sideband_remove_endpoint); + +int +xhci_sideband_stop_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = sb->eps[ep_index]; + + if (!ep || !ep->sideband || ep->sideband != sb) + return -EINVAL; + + return xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(xhci_sideband_stop_endpoint); + +/** + * xhci_sideband_get_endpoint_buffer - gets the endpoint transfer buffer address + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Returns the address of the endpoint buffer where xHC controller reads queued + * transfer TRBs from. This is the starting address of the ringbuffer where the + * sideband client should write TRBs to. + * + * Caller needs to free the returned sg_table + * + * Return: struct sg_table * if successful. NULL otherwise. + */ +struct sg_table * +xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = sb->eps[ep_index]; + + if (!ep || !ep->ring || !ep->sideband || ep->sideband != sb) + return NULL; + + return xhci_ring_to_sgtable(sb, ep->ring); +} +EXPORT_SYMBOL_GPL(xhci_sideband_get_endpoint_buffer); + +/** + * xhci_sideband_get_event_buffer - return the event buffer for this device + * @sb: sideband instance for this usb device + * + * If a secondary xhci interupter is set up for this usb device then this + * function returns the address of the event buffer where xHC writes + * the transfer completion events. + * + * Caller needs to free the returned sg_table + * + * Return: struct sg_table * if successful. NULL otherwise. + */ +struct sg_table * +xhci_sideband_get_event_buffer(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return NULL; + + return xhci_ring_to_sgtable(sb, sb->ir->event_ring); +} +EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer); + +/** + * xhci_sideband_create_interrupter - creates a new interrupter for this sideband + * @sb: sideband instance for this usb device + * @num_seg: number of event ring segments to allocate + * @ip_autoclear: IP autoclearing support such as MSI implemented + * + * Sets up a xhci interrupter that can be used for this sideband accessed usb + * device. Transfer events for this device can be routed to this interrupters + * event ring by setting the 'Interrupter Target' field correctly when queueing + * the transfer TRBs. + * Once this interrupter is created the interrupter target ID can be obtained + * by calling xhci_sideband_interrupter_id() + * + * Returns 0 on success, negative error otherwise + */ +int +xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear, u32 imod_interval) +{ + int ret = 0; + + if (!sb || !sb->xhci) + return -ENODEV; + + mutex_lock(&sb->mutex); + if (sb->ir) { + ret = -EBUSY; + goto out; + } + + sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci), + num_seg, imod_interval); + if (!sb->ir) { + ret = -ENOMEM; + goto out; + } + + sb->ir->ip_autoclear = ip_autoclear; + +out: + mutex_unlock(&sb->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); + +/** + * xhci_sideband_remove_interrupter - remove the interrupter from a sideband + * @sb: sideband instance for this usb device + * + * Removes a registered interrupt for a sideband. This would allow for other + * sideband users to utilize this interrupter. + */ +void +xhci_sideband_remove_interrupter(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return; + + mutex_lock(&sb->mutex); + xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir); + + sb->ir = NULL; + mutex_unlock(&sb->mutex); +} +EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter); + +/** + * xhci_sideband_interrupter_id - return the interrupter target id + * @sb: sideband instance for this usb device + * + * If a secondary xhci interrupter is set up for this usb device then this + * function returns the ID used by the interrupter. The sideband client + * needs to write this ID to the 'Interrupter Target' field of the transfer TRBs + * it queues on the endpoints transfer ring to ensure transfer completion event + * are written by xHC to the correct interrupter event ring. + * + * Returns interrupter id on success, negative error othgerwise + */ +int +xhci_sideband_interrupter_id(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return -ENODEV; + + return sb->ir->intr_num; +} +EXPORT_SYMBOL_GPL(xhci_sideband_interrupter_id); + +/** + * xhci_sideband_register - register a sideband for a usb device + * @intf: usb interface associated with the sideband device + * + * Allows for clients to utilize XHCI interrupters and fetch transfer and event + * ring parameters for executing data transfers. + * + * Return: pointer to a new xhci_sideband instance if successful. NULL otherwise. + */ +struct xhci_sideband * +xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_virt_device *vdev; + struct xhci_sideband *sb; + + /* + * Make sure the usb device is connected to a xhci controller. Fail + * registration if the type is anything other than XHCI_SIDEBAND_VENDOR, + * as this is the only type that is currently supported by xhci-sideband. + */ + if (!udev->slot_id || type != XHCI_SIDEBAND_VENDOR) + return NULL; + + sb = kzalloc_node(sizeof(*sb), GFP_KERNEL, dev_to_node(hcd->self.sysdev)); + if (!sb) + return NULL; + + mutex_init(&sb->mutex); + + /* check this device isn't already controlled via sideband */ + spin_lock_irq(&xhci->lock); + + vdev = xhci->devs[udev->slot_id]; + + if (!vdev || vdev->sideband) { + xhci_warn(xhci, "XHCI sideband for slot %d already in use\n", + udev->slot_id); + spin_unlock_irq(&xhci->lock); + kfree(sb); + return NULL; + } + + sb->xhci = xhci; + sb->vdev = vdev; + sb->intf = intf; + sb->type = type; + vdev->sideband = sb; + + spin_unlock_irq(&xhci->lock); + + return sb; +} +EXPORT_SYMBOL_GPL(xhci_sideband_register); + +/** + * xhci_sideband_unregister - unregister sideband access to a usb device + * @sb: sideband instance to be unregistered + * + * Unregisters sideband access to a usb device and frees the sideband + * instance. + * After this the endpoint and interrupter event buffers should no longer + * be accessed via sideband. The xhci driver can now take over handling + * the buffers. + */ +void +xhci_sideband_unregister(struct xhci_sideband *sb) +{ + struct xhci_hcd *xhci; + int i; + + if (!sb) + return; + + xhci = sb->xhci; + + mutex_lock(&sb->mutex); + for (i = 0; i < EP_CTX_PER_DEV; i++) + if (sb->eps[i]) + __xhci_sideband_remove_endpoint(sb, sb->eps[i]); + mutex_unlock(&sb->mutex); + + xhci_sideband_remove_interrupter(sb); + + spin_lock_irq(&xhci->lock); + sb->xhci = NULL; + sb->vdev->sideband = NULL; + spin_unlock_irq(&xhci->lock); + + kfree(sb); +} +EXPORT_SYMBOL_GPL(xhci_sideband_unregister); +MODULE_DESCRIPTION("xHCI sideband driver for secondary interrupter management"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8c164340a2c3..55d126d49ecc 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -697,6 +697,8 @@ struct xhci_virt_ep { int next_frame_id; /* Use new Isoch TRB layout needed for extended TBC support */ bool use_extended_tbc; + /* set if this endpoint is controlled via sideband access*/ + struct xhci_sideband *sideband; }; enum xhci_overhead_type { @@ -759,6 +761,8 @@ struct xhci_virt_device { u16 current_mel; /* Used for the debugfs interfaces. */ void *debugfs_private; + /* set if this endpoint is controlled via sideband access*/ + struct xhci_sideband *sideband; }; /* diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h new file mode 100644 index 000000000000..0f92335517ab --- /dev/null +++ b/include/linux/usb/xhci-sideband.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * xHCI host controller sideband support + * + * Copyright (c) 2023-2025, Intel Corporation. + * + * Author: Mathias Nyman + */ +#ifndef __LINUX_XHCI_SIDEBAND_H +#define __LINUX_XHCI_SIDEBAND_H + +#include +#include + +#define EP_CTX_PER_DEV 31 /* FIXME defined twice, from xhci.h */ + +struct xhci_sideband; + +enum xhci_sideband_type { + XHCI_SIDEBAND_AUDIO, + XHCI_SIDEBAND_VENDOR, +}; + +/** + * struct xhci_sideband - representation of a sideband accessed usb device. + * @xhci: The xhci host controller the usb device is connected to + * @vdev: the usb device accessed via sideband + * @eps: array of endpoints controlled via sideband + * @ir: event handling and buffer for sideband accessed device + * @mutex: mutex for sideband operations + * @intf: USB sideband client interface + * + * FIXME usb device accessed via sideband Keeping track of sideband accessed usb devices. + */ +struct xhci_sideband { + struct xhci_hcd *xhci; + struct xhci_virt_device *vdev; + struct xhci_virt_ep *eps[EP_CTX_PER_DEV]; + struct xhci_interrupter *ir; + enum xhci_sideband_type type; + + /* Synchronizing xHCI sideband operations with client drivers operations */ + struct mutex mutex; + + struct usb_interface *intf; +}; + +struct xhci_sideband * +xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type); +void +xhci_sideband_unregister(struct xhci_sideband *sb); +int +xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_stop_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_event_buffer(struct xhci_sideband *sb); +int +xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear, u32 imod_interval); +void +xhci_sideband_remove_interrupter(struct xhci_sideband *sb); +int +xhci_sideband_interrupter_id(struct xhci_sideband *sb); +#endif /* __LINUX_XHCI_SIDEBAND_H */ From patchwork Thu Jan 16 23:27:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858132 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68D99242277; Thu, 16 Jan 2025 23:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070146; cv=none; b=Kn8le4AOgPL5a1455KwSS2hCHS1Sa8fDKHY0VDlL9/olfK6kVfpvm+8ELIIGYkU1rXyxN8T2FZG4eqIiZxRRrSWtwLrelMysFTyRaKooY+Ttcvn3CyvsQNoXPvaWqGHHUZo8y+QTTfOSa1iUDnP4G7cSPZIdP24tRI691mZ6Q6E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070146; c=relaxed/simple; bh=7KTBWtugZvhwX5n9aGwuLe/yTvWxyCu0S1Si9YBSypQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q/YC1b3xdrHeKq037Cy+uCTzD7RsZPvggIjx/DR0pUox7pGUvjl1jSZvdrQTwMbfsvQd1akvCWRmPz9ZdNOdo7XPrKKtbg7TKNhhL83VIGEBnDhYIN20WZ3xxvA/euhsUijEcNEus10kxSFOprTw+G6BdVctJawQiupk2GWy7HY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=QF5sJhi3; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="QF5sJhi3" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GKwnm8028777; Thu, 16 Jan 2025 23:28:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= SHieyDg2X64OItzOVzxhREShaPtGca6Zt5seT1MFC4U=; b=QF5sJhi3Bqvk6rSN SkbbHQuoNGLzi9Yq5gYi9sxJhsQPd4ljSt3XNkIdGG4KQFhXxUt/HCrMeKpxYCb/ R+GRQSK097GmOHQg4vmJWRMzIQED2RaePkMZZKLbc+HEyt2SEygVgQ4KiNKuHM/U RdqTUMYuG4MObhHq09tshVUtCgK0zKO1et7gbD9ZvYNYq0q9ebJ9bAiFFlwYf19H rxoBca4erVxqYbSzbWIpI8dVvMnKkVHC5VGfKhzy6XuaSouqANcleaxDMQzyhXot 2w4vpxBiOSM20flyak/AT9/8gNRoH6JttoeHyVgKbYWMWt3LSOOhdQGztqPsLfq7 /Q0i5w== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4479mf883c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:43 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSf8k031813 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:42 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:41 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 03/31] usb: host: xhci-mem: Allow for interrupter clients to choose specific index Date: Thu, 16 Jan 2025 15:27:56 -0800 Message-ID: <20250116232824.3748438-4-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: YaLdhc8Eg5V2Kh512G-rMmBOegMLK_rO X-Proofpoint-ORIG-GUID: YaLdhc8Eg5V2Kh512G-rMmBOegMLK_rO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 bulkscore=0 clxscore=1015 suspectscore=0 lowpriorityscore=0 priorityscore=1501 mlxlogscore=807 mlxscore=0 malwarescore=0 phishscore=0 spamscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Some clients may operate only on a specific XHCI interrupter instance. Allow for the associated class driver to request for the interrupter that it requires. Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci-mem.c | 24 ++++++++++++++---------- drivers/usb/host/xhci-sideband.c | 5 +++-- drivers/usb/host/xhci.h | 2 +- include/linux/usb/xhci-sideband.h | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index a9129f5e3dce..2f6e1ed4c678 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2332,14 +2332,15 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, struct xhci_interrupter * xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, - u32 imod_interval) + u32 imod_interval, unsigned int intr_num) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_interrupter *ir; unsigned int i; int err = -ENOSPC; - if (!xhci->interrupters || xhci->max_interrupters <= 1) + if (!xhci->interrupters || xhci->max_interrupters <= 1 || + intr_num >= xhci->max_interrupters) return NULL; ir = xhci_alloc_interrupter(xhci, segs, GFP_KERNEL); @@ -2347,15 +2348,18 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, return NULL; spin_lock_irq(&xhci->lock); - - /* Find available secondary interrupter, interrupter 0 is reserved for primary */ - for (i = 1; i < xhci->max_interrupters; i++) { - if (xhci->interrupters[i] == NULL) { - err = xhci_add_interrupter(xhci, ir, i); - break; + if (!intr_num) { + /* Find available secondary interrupter, interrupter 0 is reserved for primary */ + for (i = 1; i < xhci->max_interrupters; i++) { + if (!xhci->interrupters[i]) { + err = xhci_add_interrupter(xhci, ir, i); + break; + } } + } else { + if (!xhci->interrupters[intr_num]) + err = xhci_add_interrupter(xhci, ir, intr_num); } - spin_unlock_irq(&xhci->lock); if (err) { @@ -2371,7 +2375,7 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, i, imod_interval); xhci_dbg(xhci, "Add secondary interrupter %d, max interrupters %d\n", - i, xhci->max_interrupters); + ir->intr_num, xhci->max_interrupters); return ir; } diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c index 19c58ae60414..742bbc6c2d9b 100644 --- a/drivers/usb/host/xhci-sideband.c +++ b/drivers/usb/host/xhci-sideband.c @@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer); */ int xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, - bool ip_autoclear, u32 imod_interval) + bool ip_autoclear, u32 imod_interval, int intr_num) { int ret = 0; @@ -273,7 +273,8 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, } sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci), - num_seg, imod_interval); + num_seg, imod_interval, + intr_num); if (!sb->ir) { ret = -ENOMEM; goto out; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ae604f37f757..06c69d0c7f99 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1843,7 +1843,7 @@ void xhci_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_interrupter * xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, - u32 imod_interval); + u32 imod_interval, unsigned int intr_num); void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir); void xhci_skip_sec_intr_events(struct xhci_hcd *xhci, diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h index 0f92335517ab..7ec23e6e27d0 100644 --- a/include/linux/usb/xhci-sideband.h +++ b/include/linux/usb/xhci-sideband.h @@ -65,7 +65,7 @@ struct sg_table * xhci_sideband_get_event_buffer(struct xhci_sideband *sb); int xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, - bool ip_autoclear, u32 imod_interval); + bool ip_autoclear, u32 imod_interval, int intr_num); void xhci_sideband_remove_interrupter(struct xhci_sideband *sb); int From patchwork Thu Jan 16 23:27:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858139 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47AC41DDC02; Thu, 16 Jan 2025 23:29:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070142; cv=none; b=H7oXnggv2OgzLbEx/QILFK0aJ6ejv1f1M2vY89theEoFqWDB5sltBkHyHZvV0QUmjQrSbVJSK56cs4N6UAJbNvplkpUn+SxB8Odv5DgFcjsaKooZD37m2i8Ig/M55Vmk+ArWUrZpStoksjNRhOPJY9VIQkJ03/7bqhnwzPxBjUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070142; c=relaxed/simple; bh=ExFqJhmnauBUraYydgWTAinjnLgJftMnbRycks90ztc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HekICPGs+f4xcLCuUyIuECKC1pnlPnaZu1kWmfBds8XYqNc0kgGlqjCDUzfppJo/HnPbx+O21spnCQSHK4wEs2t9oO8yVumE6zBMXFj6UmUMk6mcvIAxjHuhaat8RaTnEmugb6LYDRTvd1FRu+ns9CGfx0BHv5WS50ELXvPSELg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=coC4nYnl; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="coC4nYnl" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GDqaL8017230; Thu, 16 Jan 2025 23:28:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= BZG0yH4nI6h7jBPY+LVBdvPQNn0+fsbrLTtouu8dNx0=; b=coC4nYnlMvakX0Qg baEqSHjWm61By0mlBIxhebPX/XB2RhUtD4OLBK5NZBddnw92Hsldb/6JeRQ+RAbG 7p+dE4dbScPvgcnmyb6QE2+w7anRWcV7S6HvJSY5FTaoK9fAOdcxQeytx1eQgn2z wSdoAsFJ5JuV8NwkCklkpzLO4UyYGRdJAqfKB7FxYT/iQum0mOnOY4nrxj6Oko2v VVHyH7KbU6qrbMFhBO5CNpxm+91qoyBnLyIGFZZ8nySIgZo0k44lD7ffCAbRYika KaaAuFh/Phm84CbWN21co/Uksvm2YSI/kh05eKdAmvDw6T8LvprlJaExkh58GlL0 Yf70/g== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473cqh8ke-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:43 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSg8S022791 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:42 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:42 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 05/31] usb: host: xhci: Notify xHCI sideband on transfer ring free Date: Thu, 16 Jan 2025 15:27:58 -0800 Message-ID: <20250116232824.3748438-6-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: 6gxsfEEBmfR9aPdy4KmJiVLC95qY3JSm X-Proofpoint-GUID: 6gxsfEEBmfR9aPdy4KmJiVLC95qY3JSm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 phishscore=0 spamscore=0 bulkscore=0 mlxlogscore=830 adultscore=0 mlxscore=0 malwarescore=0 clxscore=1015 priorityscore=1501 impostorscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 In the case of handling a USB bus reset, the xhci_discover_or_reset_device can run without first notifying the xHCI sideband client driver to stop or prevent the use of the transfer ring. It was seen that when a bus reset situation happened, the USB offload driver was attempting to fetch the xHCI transfer ring information, which was already freed. Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci-sideband.c | 29 ++++++++++++++++++++++++++++- drivers/usb/host/xhci.c | 3 +++ include/linux/usb/xhci-sideband.h | 30 +++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c index 742bbc6c2d9b..d49f9886dd84 100644 --- a/drivers/usb/host/xhci-sideband.c +++ b/drivers/usb/host/xhci-sideband.c @@ -88,6 +88,30 @@ __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *e /* sideband api functions */ +/** + * xhci_sideband_notify_ep_ring_free - notify client of xfer ring free + * @sb: sideband instance for this usb device + * @ep_index: usb endpoint index + * + * Notifies the xHCI sideband client driver of a xHCI transfer ring free + * routine. This will allow for the client to ensure that all transfers + * are completed. + * + * The callback should be synchronous, as the ring free happens after. + */ +void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb, + unsigned int ep_index) +{ + struct xhci_sideband_event evt; + + evt.type = XHCI_SIDEBAND_XFER_RING_FREE; + evt.evt_data = &ep_index; + + if (sb->notify_client) + sb->notify_client(sb->intf, &evt); +} +EXPORT_SYMBOL_GPL(xhci_sideband_notify_ep_ring_free); + /** * xhci_sideband_add_endpoint - add endpoint to sideband access list * @sb: sideband instance for this usb device @@ -342,7 +366,9 @@ EXPORT_SYMBOL_GPL(xhci_sideband_interrupter_id); * Return: pointer to a new xhci_sideband instance if successful. NULL otherwise. */ struct xhci_sideband * -xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type) +xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type, + int (*notify_client)(struct usb_interface *intf, + struct xhci_sideband_event *evt)) { struct usb_device *udev = interface_to_usbdev(intf); struct usb_hcd *hcd = bus_to_hcd(udev->bus); @@ -381,6 +407,7 @@ xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type) sb->vdev = vdev; sb->intf = intf; sb->type = type; + sb->notify_client = notify_client; vdev->sideband = sb; spin_unlock_irq(&xhci->lock); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 514a36914ed9..972395d297f1 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -3909,6 +3910,8 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, } if (ep->ring) { + if (ep->sideband) + xhci_sideband_notify_ep_ring_free(ep->sideband, i); xhci_debugfs_remove_endpoint(xhci, virt_dev, i); xhci_free_endpoint_ring(xhci, virt_dev, i); } diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h index 7ec23e6e27d0..233c3e16d804 100644 --- a/include/linux/usb/xhci-sideband.h +++ b/include/linux/usb/xhci-sideband.h @@ -21,6 +21,20 @@ enum xhci_sideband_type { XHCI_SIDEBAND_VENDOR, }; +enum xhci_sideband_notify_type { + XHCI_SIDEBAND_XFER_RING_FREE, +}; + +/** + * struct xhci_sideband_event - sideband event + * @type: notifier type + * @evt_data: event data + */ +struct xhci_sideband_event { + enum xhci_sideband_notify_type type; + void *evt_data; +}; + /** * struct xhci_sideband - representation of a sideband accessed usb device. * @xhci: The xhci host controller the usb device is connected to @@ -29,6 +43,7 @@ enum xhci_sideband_type { * @ir: event handling and buffer for sideband accessed device * @mutex: mutex for sideband operations * @intf: USB sideband client interface + * @notify_client: callback for xHCI sideband sequences * * FIXME usb device accessed via sideband Keeping track of sideband accessed usb devices. */ @@ -43,10 +58,14 @@ struct xhci_sideband { struct mutex mutex; struct usb_interface *intf; + int (*notify_client)(struct usb_interface *intf, + struct xhci_sideband_event *evt); }; struct xhci_sideband * -xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type); +xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type, + int (*notify_client)(struct usb_interface *intf, + struct xhci_sideband_event *evt)); void xhci_sideband_unregister(struct xhci_sideband *sb); int @@ -70,4 +89,13 @@ void xhci_sideband_remove_interrupter(struct xhci_sideband *sb); int xhci_sideband_interrupter_id(struct xhci_sideband *sb); + +#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) +void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb, + unsigned int ep_index); +#else +static inline void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb, + unsigned int ep_index) +{ } +#endif /* IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) */ #endif /* __LINUX_XHCI_SIDEBAND_H */ From patchwork Thu Jan 16 23:27:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858125 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94882252CCF; Thu, 16 Jan 2025 23:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070160; cv=none; b=XRBSkaZTiw0yYSemkdv7yMuIBP8mPs+hwqi75hvn0zlUvpN+oW8ixB12rNahWha2VJqQmgWc1iJmaQGJ3b4YQETvkyGL6G+YstRgjo1dC7SbESKGplLnqjSSihxv9WXzt83E+0tk+AwrGutMCRzumy0AkuQWuPTKQ7jfr3kzhSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070160; c=relaxed/simple; bh=lrY07dFN17mj8YotedNN3XLX5OpG0TeiO1A2NSHdYpk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=q8d5bawjJ/MgPSQP32+Qyy6YcOu/jPViAClhJV5zDCZV3tnNaYwLDfpth/QB2dPW74lKKm79VMzr4A0X+q+GPrQm3n/SmQotoVgytsxxsc8y0EqQTXSdJRMW2owRS0oEvOhHEjTlof4yt+SVxmIZ/as9IG+rNfF46KlfsmCeFDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=adPO63gW; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="adPO63gW" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GEJuQa013813; Thu, 16 Jan 2025 23:28:44 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= o4wJDwyWx4vmV3ZXYYC5xJZEIcDVCQrO6adotwZutyc=; b=adPO63gWOsPr+aM4 0rrKbxfPRL6MxU/skAexv7zE65KoYkjkooe/A6m7fDDgKLwzuwARKVlSKIU86pri mnvax/lpg+KKW/raW9Tz4bez1U1Ld/i5IVai/Au5a/tUvn3EuXgwkFAhIJCvENjP gQIajzN6fFep+Nb3hrIiPh4EJ0X1rsm5Rk3FoCv5apFDGCO8HwvrnilokUtrK0co Oi3v5rx+f4yyCnwCCt0Wx6qh0rQSgbXgnYelzLoWi3a63az7NYN/TuvUyBGCR/sF 0NG6daHe6Cw1yGgeUo61VH7LYtacHLCAr9jL//AgabANNbLOWR/eqBFl/uThWIDl TaKn6w== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473se17ew-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:44 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNShbl032066 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:43 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:42 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 06/31] usb: dwc3: Specify maximum number of XHCI interrupters Date: Thu, 16 Jan 2025 15:27:59 -0800 Message-ID: <20250116232824.3748438-7-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: kq-oMb2TbN4w5MZuVNgltg9YjPuKewjp X-Proofpoint-ORIG-GUID: kq-oMb2TbN4w5MZuVNgltg9YjPuKewjp X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 spamscore=0 adultscore=0 mlxscore=0 bulkscore=0 impostorscore=0 malwarescore=0 suspectscore=0 mlxlogscore=872 lowpriorityscore=0 clxscore=1015 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Allow for the DWC3 host driver to pass along XHCI property that defines how many interrupters to allocate. This is in relation for the number of event rings that can be potentially used by other processors within the system. Acked-by: Thinh Nguyen Signed-off-by: Wesley Cheng --- drivers/usb/dwc3/core.c | 12 ++++++++++++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/host.c | 3 +++ 3 files changed, 17 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7578c5133568..bc727af8cfd6 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1684,6 +1684,7 @@ static void dwc3_get_properties(struct dwc3 *dwc) u8 tx_thr_num_pkt_prd = 0; u8 tx_max_burst_prd = 0; u8 tx_fifo_resize_max_num; + u16 num_hc_interrupters; const char *usb_psy_name; int ret; @@ -1706,6 +1707,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) */ tx_fifo_resize_max_num = 6; + /* default to a single XHCI interrupter */ + num_hc_interrupters = 1; + dwc->maximum_speed = usb_get_maximum_speed(dev); dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev); dwc->dr_mode = usb_get_dr_mode(dev); @@ -1759,6 +1763,12 @@ static void dwc3_get_properties(struct dwc3 *dwc) &tx_thr_num_pkt_prd); device_property_read_u8(dev, "snps,tx-max-burst-prd", &tx_max_burst_prd); + device_property_read_u16(dev, "num-hc-interrupters", + &num_hc_interrupters); + /* DWC3 core allowed to have a max of 8 interrupters */ + if (num_hc_interrupters > 8) + num_hc_interrupters = 8; + dwc->do_fifo_resize = device_property_read_bool(dev, "tx-fifo-resize"); if (dwc->do_fifo_resize) @@ -1847,6 +1857,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->imod_interval = 0; dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num; + + dwc->num_hc_interrupters = num_hc_interrupters; } /* check whether the core supports IMOD */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 914fe79d08e8..5a7522e57bbf 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1081,6 +1081,7 @@ struct dwc3_scratchpad_array { * @tx_max_burst_prd: max periodic ESS transmit burst size * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize * @clear_stall_protocol: endpoint number that requires a delayed status phase + * @num_hc_interrupters: number of host controller interrupters * @hsphy_interface: "utmi" or "ulpi" * @connected: true when we're connected to a host, false otherwise * @softconnect: true when gadget connect is called, false when disconnect runs @@ -1328,6 +1329,7 @@ struct dwc3 { u8 tx_max_burst_prd; u8 tx_fifo_resize_max_num; u8 clear_stall_protocol; + u16 num_hc_interrupters; const char *hsphy_interface; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index b48e108fc8fe..1c513bf8002e 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -182,6 +182,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (DWC3_VER_IS_WITHIN(DWC3, ANY, 300A)) props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped"); + props[prop_idx++] = PROPERTY_ENTRY_U16("num-hc-interrupters", + dwc->num_hc_interrupters); + if (prop_idx) { ret = device_create_managed_software_node(&xhci->dev, props, NULL); if (ret) { From patchwork Thu Jan 16 23:28:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858131 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2601D2442E3; Thu, 16 Jan 2025 23:29:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070147; cv=none; b=XB3IqJFQokhFEX63emcIP0jKOfKts90AJr1QF1kcE0kjWOr4fzFlZ+mCcQpRu4lglZTGAdWh6xeD+LzHg22TMceGIDtrYBKH+DYjzAztI6nfFQN1E5Xwy7V8DBYjEZW7pKBTESqVbVwElm/LJTENV/cH67sTac2F6A5zXMRacgs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070147; c=relaxed/simple; bh=8LFfZvsEZtb7Rvtz20t3R2gyJJLgeD0OdIXEJmaqk0Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OxdKqiBUHZcbyy63TFudRwhFbNrT6kVy75HS6UmH/72z1qpQTB0HuUrozkFeVuXPOEzmpTJsb1gIH1+rTCGRAgvDtdkAMoifz6oKfLPTWQhf1zT1u1Zqq+x66hchYwbrYzaf9OCgcIST8rj4CLKceLmTajvbABZHn0btq2ZBbRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=kG3adfvg; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="kG3adfvg" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN8nTF013805; Thu, 16 Jan 2025 23:28:45 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ttnVezO587R3SiE4KfuBdhmGnpXGor59yM9glqfHyt0=; b=kG3adfvgkkrGEiQy eVVFVeRiN9QhRypOjjL2VtMIUCorFdGcKA59Vg6sMl6UJyJxAOxiCDUGQnJAyFhk U4zJSQCguiXRHjVqo47jVTS/3RTjxWU/OjUYpk3boa3dDz/M6vWdWT9tje1xOAze JrAE3UiNm5BbHKdA0Zf27NQhTJDadtIrl/Tp4qnU1PEvAYecsSl2O14LrE7QULv2 nkgoTnCwMXQI7iZRh4Ob58b7pJ0oC1hzNo7vBUCvpFFqFTNvaNWdG789BfMlqGT/ E+8rCC7JWm7ImrJEz5t58vmzadeq4P694yQRCQntvVzK4noGHWz513gDVbPXW/30 NxMCOw== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:44 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNShdq032069 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:44 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:43 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 09/31] ALSA: usb-audio: Check for support for requested audio format Date: Thu, 16 Jan 2025 15:28:02 -0800 Message-ID: <20250116232824.3748438-10-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: Pp_GSRUd4YtD3YlLiwjr6tnlS18szYgy X-Proofpoint-ORIG-GUID: Pp_GSRUd4YtD3YlLiwjr6tnlS18szYgy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Allow for checks on a specific USB audio device to see if a requested PCM format is supported. This is needed for support when playback is initiated by the ASoC USB backend path. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Wesley Cheng --- sound/usb/card.c | 32 ++++++++++++++++++++++++++++++++ sound/usb/card.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index a0087bde684c..6c5b0e02e57b 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -119,6 +119,38 @@ static DEFINE_MUTEX(register_mutex); static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; static struct usb_driver usb_audio_driver; +/* + * Checks to see if requested audio profile, i.e sample rate, # of + * channels, etc... is supported by the substream associated to the + * USB audio device. + */ +struct snd_usb_stream * +snd_usb_find_suppported_substream(int card_idx, struct snd_pcm_hw_params *params, + int direction) +{ + struct snd_usb_audio *chip; + struct snd_usb_substream *subs; + struct snd_usb_stream *as; + + /* + * Register mutex is held when populating and clearing usb_chip + * array. + */ + guard(mutex)(®ister_mutex); + chip = usb_chip[card_idx]; + + if (chip && enable[card_idx]) { + list_for_each_entry(as, &chip->pcm_list, list) { + subs = &as->substream[direction]; + if (snd_usb_find_substream_format(subs, params)) + return as; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(snd_usb_find_suppported_substream); + /* * disconnect streams * called from usb_audio_disconnect() diff --git a/sound/usb/card.h b/sound/usb/card.h index 6ec95b2edf86..4f4f3f39b7fa 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -207,4 +207,7 @@ struct snd_usb_stream { struct list_head list; }; +struct snd_usb_stream * +snd_usb_find_suppported_substream(int card_idx, struct snd_pcm_hw_params *params, + int direction); #endif /* __USBAUDIO_CARD_H */ From patchwork Thu Jan 16 23:28:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858127 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A82791F78FB; Thu, 16 Jan 2025 23:29:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070152; cv=none; b=YRsITKAw51tb+UmEL2cBsU3w1ofuQdOY7puE6MjVilaFpp2HDppaSwYCHSxE0qdJIzHeqMbNdOWE8q7j67ySvoPXfzHYiESZR1vd+v2hsScx9sVihXo9z9U8kPjDaYuP2uocnXmzJDx+jBrytu6yt4PuQ9fzh1+qAPfPpxKK1ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070152; c=relaxed/simple; bh=uIcvlah9pUzgCXwSqziN5w8ZwIKpHRV+zhpT5buMOGs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hihNEI9Pl9Jh0124BBvKCj7zAPGEr6qc8iRwj2YWgifLpYwLIk/KZH6SD+EpMpRBmTaOWeLlVJaYhwEAkowS38Z0LZu4M1X7HSzo9yR13ToTvEsoLg/H5FYHTE0JZHSYDvUjcdtWsC9Bl6qgn1tnOhis/LcLkmE953zn7cLnFp0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=mdNrVwW3; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="mdNrVwW3" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN8nTG013805; Thu, 16 Jan 2025 23:28:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= Rr5LN+XV+yA3jv5JDATkEchdIjgdKktL3nGi4+1+XGY=; b=mdNrVwW3NMCFt77W CqtqxMKD9NjIsamO1F7vWT/8sIhBGCY3sqYg3OUWKyZ3QejAC7nO0ro1AfiTLyri z7/Y3gNnlGAlKGGIamT2h5MvYyYv4a+rVJ/4ddCCATg2os075BdSXF+Lcpsjm+t2 MuGKeruTWqHjdy8zMvnByhi3iw85Ql59simRU8SqNQtpXXejmWK9zl3b8qwOJA12 HWBNlLXF9+sQIkv6QCV4JdE52fjMlR4TinUKudIIM58ZEm2mB6btF1Go8k6fI5Kc R4PyI0OsGXh0NkUEXgPs+hEPfZKoDdHPzJungNNrqsWjK0PMire/Cz5Eti9NYBCS i9J/7g== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:46 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSjKj032076 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:45 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:44 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 14/31] ASoC: Add SoC USB APIs for adding an USB backend Date: Thu, 16 Jan 2025 15:28:07 -0800 Message-ID: <20250116232824.3748438-15-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: UCSLkCumPazqjg_iIYW8U09VjX5grH4G X-Proofpoint-ORIG-GUID: UCSLkCumPazqjg_iIYW8U09VjX5grH4G X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Some platforms may have support for offloading USB audio devices to a dedicated audio DSP. Introduce a set of APIs that allow for management of USB sound card and PCM devices enumerated by the USB SND class driver. This allows for the ASoC components to be aware of what USB devices are available for offloading. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Wesley Cheng --- include/sound/soc-usb.h | 97 ++++++++++++++++++ sound/soc/Kconfig | 10 ++ sound/soc/Makefile | 2 + sound/soc/soc-usb.c | 220 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 329 insertions(+) create mode 100644 include/sound/soc-usb.h create mode 100644 sound/soc/soc-usb.c diff --git a/include/sound/soc-usb.h b/include/sound/soc-usb.h new file mode 100644 index 000000000000..bd4c5632bb62 --- /dev/null +++ b/include/sound/soc-usb.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __LINUX_SND_SOC_USB_H +#define __LINUX_SND_SOC_USB_H + +#include + +/** + * struct snd_soc_usb_device + * @card_idx - sound card index associated with USB device + * @chip_idx - USB sound chip array index + * @cpcm_idx - capture PCM index array associated with USB device + * @ppcm_idx - playback PCM index array associated with USB device + * @num_capture - number of capture streams + * @num_playback - number of playback streams + * @list - list head for SoC USB devices + **/ +struct snd_soc_usb_device { + int card_idx; + int chip_idx; + + /* PCM index arrays */ + unsigned int *cpcm_idx; /* TODO: capture path is not tested yet */ + unsigned int *ppcm_idx; + int num_capture; /* TODO: capture path is not tested yet */ + int num_playback; + + struct list_head list; +}; + +/** + * struct snd_soc_usb + * @list - list head for SND SOC struct list + * @component - reference to ASoC component + * @connection_status_cb - callback to notify connection events + * @priv_data - driver data + **/ +struct snd_soc_usb { + struct list_head list; + struct snd_soc_component *component; + int (*connection_status_cb)(struct snd_soc_usb *usb, + struct snd_soc_usb_device *sdev, + bool connected); + void *priv_data; +}; + +#if IS_ENABLED(CONFIG_SND_SOC_USB) +int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev); +int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev); +void *snd_soc_usb_find_priv_data(struct device *usbdev); + +struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component, + void *data); +void snd_soc_usb_free_port(struct snd_soc_usb *usb); +void snd_soc_usb_add_port(struct snd_soc_usb *usb); +void snd_soc_usb_remove_port(struct snd_soc_usb *usb); +#else +static inline int snd_soc_usb_connect(struct device *usbdev, + struct snd_soc_usb_device *sdev) +{ + return -ENODEV; +} + +static inline int snd_soc_usb_disconnect(struct device *usbdev, + struct snd_soc_usb_device *sdev) +{ + return -EINVAL; +} + +static inline void *snd_soc_usb_find_priv_data(struct device *usbdev) +{ + return NULL; +} + +static inline struct snd_soc_usb * +snd_soc_usb_allocate_port(struct snd_soc_component *component, void *data) +{ + return ERR_PTR(-ENOMEM); +} + +static inline void snd_soc_usb_free_port(struct snd_soc_usb *usb) +{ } + +static inline void snd_soc_usb_add_port(struct snd_soc_usb *usb) +{ + return -EINVAL; +} + +static inline void snd_soc_usb_remove_port(struct snd_soc_usb *usb) +{ + return -ENODEV; +} +#endif /* IS_ENABLED(CONFIG_SND_SOC_USB) */ +#endif /*__LINUX_SND_SOC_USB_H */ diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 5efba76abb31..d34b4fdb2930 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -84,6 +84,16 @@ config SND_SOC_UTILS_KUNIT_TEST config SND_SOC_ACPI tristate +config SND_SOC_USB + tristate "SoC based USB audio offloading" + depends on SND_USB_AUDIO + help + Enable this option if an ASoC platform card has support to handle + USB audio offloading. This enables the SoC USB layer, which will + notifies the ASoC USB DPCM backend DAI link about available USB audio + devices. Based on the notifications, sequences to enable the audio + stream can be taken based on the design. + # All the supported SoCs source "sound/soc/adi/Kconfig" source "sound/soc/amd/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 08baaa11d813..b0541d0583f2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -35,6 +35,8 @@ endif obj-$(CONFIG_SND_SOC_ACPI) += snd-soc-acpi.o +obj-$(CONFIG_SND_SOC_USB) += soc-usb.o + obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ obj-$(CONFIG_SND_SOC) += generic/ diff --git a/sound/soc/soc-usb.c b/sound/soc/soc-usb.c new file mode 100644 index 000000000000..3b8e47e3f469 --- /dev/null +++ b/sound/soc/soc-usb.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include "../usb/card.h" + +static DEFINE_MUTEX(ctx_mutex); +static LIST_HEAD(usb_ctx_list); + +static struct device_node *snd_soc_find_phandle(struct device *dev) +{ + struct device_node *node; + + node = of_parse_phandle(dev->of_node, "usb-soc-be", 0); + if (!node) + return ERR_PTR(-ENODEV); + + return node; +} + +static struct snd_soc_usb *snd_soc_usb_ctx_lookup(struct device_node *node) +{ + struct snd_soc_usb *ctx; + + if (!node) + return NULL; + + list_for_each_entry(ctx, &usb_ctx_list, list) { + if (ctx->component->dev->of_node == node) + return ctx; + } + + return NULL; +} + +static struct snd_soc_usb *snd_soc_find_usb_ctx(struct device *dev) +{ + struct snd_soc_usb *ctx; + struct device_node *node; + + node = snd_soc_find_phandle(dev); + if (!IS_ERR(node)) { + ctx = snd_soc_usb_ctx_lookup(node); + of_node_put(node); + } else { + ctx = snd_soc_usb_ctx_lookup(dev->of_node); + } + + return ctx ? ctx : NULL; +} + +/** + * snd_soc_usb_find_priv_data() - Retrieve private data stored + * @usbdev: device reference + * + * Fetch the private data stored in the USB SND SoC structure. + * + */ +void *snd_soc_usb_find_priv_data(struct device *usbdev) +{ + struct snd_soc_usb *ctx; + + mutex_lock(&ctx_mutex); + ctx = snd_soc_find_usb_ctx(usbdev); + mutex_unlock(&ctx_mutex); + + return ctx ? ctx->priv_data : NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_find_priv_data); + +/** + * snd_soc_usb_allocate_port() - allocate a SoC USB port for offloading support + * @component: USB DPCM backend DAI component + * @num_streams: number of offloading sessions supported + * @data: private data + * + * Allocate and initialize a SoC USB port. The SoC USB port is used to communicate + * different USB audio devices attached, in order to start audio offloading handled + * by an ASoC entity. USB device plug in/out events are signaled with a + * notification, but don't directly impact the memory allocated for the SoC USB + * port. + * + */ +struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component, + void *data) +{ + struct snd_soc_usb *usb; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + usb->component = component; + usb->priv_data = data; + + return usb; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_allocate_port); + +/** + * snd_soc_usb_free_port() - free a SoC USB port used for offloading support + * @usb: allocated SoC USB port + + * Free and remove the SoC USB port from the available list of ports. This will + * ensure that the communication between USB SND and ASoC is halted. + * + */ +void snd_soc_usb_free_port(struct snd_soc_usb *usb) +{ + snd_soc_usb_remove_port(usb); + kfree(usb); +} +EXPORT_SYMBOL_GPL(snd_soc_usb_free_port); + +/** + * snd_soc_usb_add_port() - Add a USB backend port + * @usb: soc usb port to add + * + * Register a USB backend DAI link to the USB SoC framework. Memory is allocated + * as part of the USB backend DAI link. + * + */ +void snd_soc_usb_add_port(struct snd_soc_usb *usb) +{ + mutex_lock(&ctx_mutex); + list_add_tail(&usb->list, &usb_ctx_list); + mutex_unlock(&ctx_mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_usb_add_port); + +/** + * snd_soc_usb_remove_port() - Remove a USB backend port + * @usb: soc usb port to remove + * + * Remove a USB backend DAI link from USB SoC. Memory is freed when USB backend + * DAI is removed, or when snd_soc_usb_free_port() is called. + * + */ +void snd_soc_usb_remove_port(struct snd_soc_usb *usb) +{ + struct snd_soc_usb *ctx, *tmp; + + mutex_lock(&ctx_mutex); + list_for_each_entry_safe(ctx, tmp, &usb_ctx_list, list) { + if (ctx == usb) { + list_del(&ctx->list); + break; + } + } + mutex_unlock(&ctx_mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_usb_remove_port); + +/** + * snd_soc_usb_connect() - Notification of USB device connection + * @usbdev: USB bus device + * @sdev: USB SND device to add + * + * Notify of a new USB SND device connection. The sdev->card_idx can be used to + * handle how the DPCM backend selects, which device to enable USB offloading + * on. + * + */ +int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev) +{ + struct snd_soc_usb *ctx; + + if (!usbdev) + return -ENODEV; + + mutex_lock(&ctx_mutex); + ctx = snd_soc_find_usb_ctx(usbdev); + if (!ctx) + goto exit; + + if (ctx->connection_status_cb) + ctx->connection_status_cb(ctx, sdev, true); + +exit: + mutex_unlock(&ctx_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_connect); + +/** + * snd_soc_usb_disconnect() - Notification of USB device disconnection + * @usbdev: USB bus device + * @sdev: USB SND device to remove + * + * Notify of a new USB SND device disconnection to the USB backend. + * + */ +int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev) +{ + struct snd_soc_usb *ctx; + + if (!usbdev) + return -ENODEV; + + mutex_lock(&ctx_mutex); + ctx = snd_soc_find_usb_ctx(usbdev); + if (!ctx) + goto exit; + + if (ctx->connection_status_cb) + ctx->connection_status_cb(ctx, sdev, false); + +exit: + mutex_unlock(&ctx_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_disconnect); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SoC USB driver for offloading"); From patchwork Thu Jan 16 23:28:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858130 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD252246A27; Thu, 16 Jan 2025 23:29:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070148; cv=none; b=XCir86st6alK8seodaHDX00bjt1e/+lPqg8D3bLME/8oA5GoTg8LXM3vqjclLJ/7NjtI6jmPw56zn53MHBnFxJ+IlUJAp2VuDj8m+vBO7j2zBlyg1G7Jd1GwqbiAHFz4t6mA1liXxklZ0DdId+Dsw1tSbG38QUQw3nX7nhzl93w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070148; c=relaxed/simple; bh=X/Bvl1S4+JNrZMbRaJr50aupT5ChpkpNPUFwxAxdL+A=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ETwBz+PlU7S86JgHcnrh86iRTm8wTQGc8XAfgvo9XyOWMfMnw5+zFmsgG1YX7xVPj44dSZgx4odsBHNtUNSxe9EE2k73kqTjgxJVZR+aspqXrXiMmaqLGWzEB/68aHAStnwzQQmyoT0uQNRLHGzXcGcAmWDQsn+/RZN7n9OKSns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=BzX0dpKo; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="BzX0dpKo" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN7gEG011119; Thu, 16 Jan 2025 23:28:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= xByViXVdmWC7x1UA5M9loILdhYftVOahYhTDpfeOINY=; b=BzX0dpKoiixuCRA9 FQ8KcvVzLrnCKTEETDAnDBqX4wZqd1OntvTcloJBlGuD84e8bKJwtLG5CFiO7lOQ 0xeo6sHa+qljS34k/hYCGdu7W4bDmBQOuKP9LvmFE8MlFeSavrSSmg137GpBUQ+H jECwbm7PniJ3L3J0J0FL5gfN8JBUSH7nqN8AWkTvRHfDqlu1695udNwtIP5sxWvj IrSf4dceIDuA3v4wHGkIY9AzNiu66qx7jHSdJm/UF4H7fj55sAD0xDfqtfKzKBl6 rbLapsiyKJihHwsssHoI66o8orBRmEQeayUTo4pAls84gUHg9fb9EXJ53p89EVwR fkjfQQ== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:46 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSjdX019290 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:45 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:45 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 15/31] ASoC: usb: Add PCM format check API for USB backend Date: Thu, 16 Jan 2025 15:28:08 -0800 Message-ID: <20250116232824.3748438-16-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: RIuazPzl8vqF2GlMbzsBZNF55UTFPmbT X-Proofpoint-ORIG-GUID: RIuazPzl8vqF2GlMbzsBZNF55UTFPmbT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Introduce a helper to check if a particular PCM format is supported by the USB audio device connected. If the USB audio device does not have an audio profile which can support the requested format, then notify the USB backend. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Wesley Cheng --- include/sound/soc-usb.h | 11 +++++++++++ sound/soc/soc-usb.c | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/sound/soc-usb.h b/include/sound/soc-usb.h index bd4c5632bb62..b36fdf4d0853 100644 --- a/include/sound/soc-usb.h +++ b/include/sound/soc-usb.h @@ -48,6 +48,10 @@ struct snd_soc_usb { }; #if IS_ENABLED(CONFIG_SND_SOC_USB) +int snd_soc_usb_find_supported_format(int card_idx, + struct snd_pcm_hw_params *params, + int direction); + int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev); int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev); void *snd_soc_usb_find_priv_data(struct device *usbdev); @@ -58,6 +62,13 @@ void snd_soc_usb_free_port(struct snd_soc_usb *usb); void snd_soc_usb_add_port(struct snd_soc_usb *usb); void snd_soc_usb_remove_port(struct snd_soc_usb *usb); #else +static inline int +snd_soc_usb_find_supported_format(int card_idx, struct snd_pcm_hw_params *params, + int direction) +{ + return -EINVAL; +} + static inline int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev) { diff --git a/sound/soc/soc-usb.c b/sound/soc/soc-usb.c index 3b8e47e3f469..8f7f19c55681 100644 --- a/sound/soc/soc-usb.c +++ b/sound/soc/soc-usb.c @@ -71,6 +71,32 @@ void *snd_soc_usb_find_priv_data(struct device *usbdev) } EXPORT_SYMBOL_GPL(snd_soc_usb_find_priv_data); +/** + * snd_soc_usb_find_supported_format() - Check if audio format is supported + * @card_idx: USB sound chip array index + * @params: PCM parameters + * @direction: capture or playback + * + * Ensure that a requested audio profile from the ASoC side is able to be + * supported by the USB device. + * + * Return 0 on success, negative on error. + * + */ +int snd_soc_usb_find_supported_format(int card_idx, + struct snd_pcm_hw_params *params, + int direction) +{ + struct snd_usb_stream *as; + + as = snd_usb_find_suppported_substream(card_idx, params, direction); + if (!as) + return -EOPNOTSUPP; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_find_supported_format); + /** * snd_soc_usb_allocate_port() - allocate a SoC USB port for offloading support * @component: USB DPCM backend DAI component From patchwork Thu Jan 16 23:28:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858138 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C51FA2361E7; Thu, 16 Jan 2025 23:29:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070143; cv=none; b=f1nj7WXVNRHyjrJhspk+PQLU6/wp7ErUo7g99jodUGH9cLfl1H+nYKDR8Kbu0FJ51n4Xu9hnYfD8IRArAJGbDz+hXp2FaZghJrDdkzA8FBWo2bNwY70Ynh33TqUwSEm2CbBr5qQvR2bck5i6k7BkoAYtMPCLdH/rW9QeEojjEyo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070143; c=relaxed/simple; bh=fz3dWJECQrWW8qH/MQlxfS2nNh3jM2uYIvuScZFYBG8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LEp0/DjJAOWG9mj8OvxkPONAIwJCpDlSm1PCv9MHzKPRmVuCmKRQnCnNm+WVrl/X63F569e8HLK81pVmxqnNnM2bQIEHiR/OL32NyQuHAa53cqLLcdYM4bS2iOO6bqhu0bjb2TiqDfJYKdZk/ZhQsNeZ+ZMSaDuBrixRo+MWeZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=PA9Pf7kC; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="PA9Pf7kC" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GEJkvF005439; Thu, 16 Jan 2025 23:28:47 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= E4ac7XKHLeBId41/pNXzZQDLJM9pL/sYfePnt9miOyU=; b=PA9Pf7kCv+b0mkgq jQ+krzX0JjH2LAOw9O0E1qgBqlWzq6dhT+l3zSdhkeyVR8bi+tOcwKOWFLEYqfU2 iPjmxUH7ZPdzY0OAGTch+g0ah36Jk5AaAHi5C0Csp4gOEWh6sN47sbtRN6+cGZv3 +2GigCZ/CL3SF7UyVwzuOvbrdw0e1mfAxamZxUBb94CkiPKzXrwjWV/RX3gqvV51 wMhIDESlWfeVIBFWTO4LdvbONcyFThSzRaaigcZWvO21dZWpedl0qVOOQBItfTi+ fcfyNIIW2wShHGLRbLDF2uxNA2mjK50qa0HcI9vI9RyAyxHeekGZaMyzMNcrcWvT +GYNng== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473sfs6n1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:47 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSku8032095 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:46 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:45 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 17/31] ASoC: usb: Fetch ASoC card and pcm device information Date: Thu, 16 Jan 2025 15:28:10 -0800 Message-ID: <20250116232824.3748438-18-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: yFlx7icrg1ORFLiR-V3mQjvf2cpGJNBo X-Proofpoint-ORIG-GUID: yFlx7icrg1ORFLiR-V3mQjvf2cpGJNBo X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 phishscore=0 impostorscore=0 malwarescore=0 priorityscore=1501 suspectscore=0 mlxscore=0 lowpriorityscore=0 clxscore=1015 mlxlogscore=974 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 USB SND needs to know how the USB offload path is being routed. This would allow for applications to open the corresponding sound card and pcm device when it wants to take the audio offload path. This callback should return the mapped indexes based on the USB SND device information. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Wesley Cheng --- include/sound/soc-usb.h | 25 +++++++++++++++++++++++++ sound/soc/soc-usb.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/include/sound/soc-usb.h b/include/sound/soc-usb.h index 7c4100094258..4fab9996917b 100644 --- a/include/sound/soc-usb.h +++ b/include/sound/soc-usb.h @@ -8,6 +8,11 @@ #include +enum snd_soc_usb_kctl { + SND_SOC_USB_KCTL_CARD_ROUTE, + SND_SOC_USB_KCTL_PCM_ROUTE, +}; + /** * struct snd_soc_usb_device * @card_idx - sound card index associated with USB device @@ -36,6 +41,12 @@ struct snd_soc_usb_device { * @list - list head for SND SOC struct list * @component - reference to ASoC component * @connection_status_cb - callback to notify connection events + * @update_offload_route_info - callback to fetch mapped ASoC card and pcm + * device pair. This is unrelated to the concept + * of DAPM route. The "route" argument carries + * an array used for a kcontrol output for either + * the card or pcm index. "path" determines the + * which entry to look for. (ie mapped card or pcm) * @priv_data - driver data **/ struct snd_soc_usb { @@ -44,6 +55,10 @@ struct snd_soc_usb { int (*connection_status_cb)(struct snd_soc_usb *usb, struct snd_soc_usb_device *sdev, bool connected); + int (*update_offload_route_info)(struct snd_soc_component *component, + int card, int pcm, int direction, + enum snd_soc_usb_kctl path, + long *route); void *priv_data; }; @@ -58,6 +73,9 @@ void *snd_soc_usb_find_priv_data(struct device *usbdev); int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, struct snd_soc_jack *jack); +int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route); struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component, void *data); @@ -95,6 +113,13 @@ static inline int snd_soc_usb_setup_offload_jack(struct snd_soc_component *compo return 0; } +static int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route) +{ + return -ENODEV; +} + static inline struct snd_soc_usb * snd_soc_usb_allocate_port(struct snd_soc_component *component, void *data) { diff --git a/sound/soc/soc-usb.c b/sound/soc/soc-usb.c index 23d0ef5b1031..86f0d1b9fe43 100644 --- a/sound/soc/soc-usb.c +++ b/sound/soc/soc-usb.c @@ -90,6 +90,42 @@ int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_usb_setup_offload_jack); +/** + * snd_soc_usb_update_offload_route - Find active USB offload path + * @dev - USB device to get offload status + * @card - USB card index + * @pcm - USB PCM device index + * @direction - playback or capture direction + * @route - pointer to route output array + * + * Fetch the current status for the USB SND card and PCM device indexes + * specified. The "route" argument should be an array of integers being + * used for a kcontrol output. The first element should have the selected + * card index, and the second element should have the selected pcm device + * index. + */ +int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route) +{ + struct snd_soc_usb *ctx; + int ret = -ENODEV; + + mutex_lock(&ctx_mutex); + ctx = snd_soc_find_usb_ctx(dev); + if (!ctx) + goto exit; + + if (ctx->update_offload_route_info) + ret = ctx->update_offload_route_info(ctx->component, card, pcm, + direction, path, route); +exit: + mutex_unlock(&ctx_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_update_offload_route); + /** * snd_soc_usb_find_priv_data() - Retrieve private data stored * @usbdev: device reference From patchwork Thu Jan 16 23:28:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858133 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFAC124225F; Thu, 16 Jan 2025 23:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070146; cv=none; b=V0JzwXO7fZx+ys9DC/1rk5J+TRhHywkCWEuQH3zBDm7kp+S+tdZ7C044WfslbFh7JiGMIBTk+X7RlAGLzMZY4RLtRmXFOEjp3RQuXAgB8BH83HHTFCNAsRBXMQ3oLUgai8NGpTTfFiGYQecmJGabWFRRl/CnUHHgSRkIWunr2oQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070146; c=relaxed/simple; bh=yt7+twdKeWcbNTxGt1dvAM9pw0HPJWzFoElI63wdxDg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Gy9OboNOGwWtRjR+9iCar6YV0VQ4N+r7w1v2mH+DjwledxV+THja4V+I8GOujTCn4VNaugXtgsyl3A8CZrkegC4BTUfzLWG/LJ5aRBVgK5LMpG+kKXrG4tP/fvnaRmwzyMWCdwsAuYBQakNABvTxY+P3OIsdWZRUnEDBRtxiHAI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=AO2JxSdl; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="AO2JxSdl" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GKwedW028646; Thu, 16 Jan 2025 23:28:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= /wAS0xfcEqrs1U5x6DN+htCJ72TxK2lRReVBr775xQg=; b=AO2JxSdl7t+hQDe3 H8aCSivx5h3oK+/4MIAaM4JSvkelJEbMB4nxef/KbFPAAMMh1kWdLbfxIwP8YvBm oVjBe2JZ1GpaUurtI+EK8+7QJq/P+f1qjsqjFdR4BTwz/Dq5cBAuFa46v8k/tuws y9Vvv8K3QgVj8bYE6x786d+3dh2ZDB0kuZLRN4ndXYO+av603ZAc5nY090Lv2XQ6 0gW1sr9FJ2I+Lk9GTavkRRINPp1DfyQOZ2x7LCWfxpMfMJZiMHap0t6DkoutyIEz G9rDcCurqs+4Is2fOVCsb6NFpz9t329nDxSDlSTny5xbmZls4bJhJMISaKm6cTvu aKGG1w== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4479mf883h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:47 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA01.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSkm3027133 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:46 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:46 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 19/31] ASoC: doc: Add documentation for SOC USB Date: Thu, 16 Jan 2025 15:28:12 -0800 Message-ID: <20250116232824.3748438-20-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: JaEgswExrF52aqe0iGTiHisL9HjjZJgy X-Proofpoint-ORIG-GUID: JaEgswExrF52aqe0iGTiHisL9HjjZJgy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 bulkscore=0 clxscore=1015 suspectscore=0 lowpriorityscore=0 priorityscore=1501 mlxlogscore=999 mlxscore=0 malwarescore=0 phishscore=0 spamscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 With the introduction of the soc-usb driver, add documentation highlighting details on how to utilize the new driver and how it interacts with different components in USB SND and ASoC. It provides examples on how to implement the drivers that will need to be introduced in order to enable USB audio offloading. Signed-off-by: Wesley Cheng --- Documentation/sound/soc/index.rst | 1 + Documentation/sound/soc/usb.rst | 482 ++++++++++++++++++++++++++++++ 2 files changed, 483 insertions(+) create mode 100644 Documentation/sound/soc/usb.rst diff --git a/Documentation/sound/soc/index.rst b/Documentation/sound/soc/index.rst index e57df2dab2fd..8bed8f8f48da 100644 --- a/Documentation/sound/soc/index.rst +++ b/Documentation/sound/soc/index.rst @@ -18,3 +18,4 @@ The documentation is spilt into the following sections:- jack dpcm codec-to-codec + usb diff --git a/Documentation/sound/soc/usb.rst b/Documentation/sound/soc/usb.rst new file mode 100644 index 000000000000..94c12f9d9dd1 --- /dev/null +++ b/Documentation/sound/soc/usb.rst @@ -0,0 +1,482 @@ +================ +ASoC USB support +================ + +Overview +======== +In order to leverage the existing USB sound device support in ALSA, the +ASoC USB APIs are introduced to allow the subsystems to exchange +configuration information. + +One potential use case would be to support USB audio offloading, which is +an implementation that allows for an alternate power-optimized path in the audio +subsystem to handle the transfer of audio data over the USB bus. This would +let the main processor to stay in lower power modes for longer duration. The +following is an example design of how the ASoC and ALSA pieces can be connected +together to achieve this: + +:: + + USB | ASoC + | _________________________ + | | ASoC Platform card | + | |_________________________| + | | | + | ___V____ ____V____ + | |ASoC BE | |ASoC FE | + | |DAI LNK | |DAI LNK | + | |________| |_________| + | ^ ^ ^ + | | |________| + | ___V____ | + | |SoC-USB | | + ________ ________ | | | + |USB SND |<--->|USBSND |<------------>|________| | + |(card.c)| |offld |<---------- | + |________| |________|___ | | | + ^ ^ | | | ____________V_________ + | | | | | |IPC | + __ V_______________V_____ | | | |______________________| + |USB SND (endpoint.c) | | | | ^ + |_________________________| | | | | + ^ | | | ___________V___________ + | | | |->|audio DSP | + ___________V_____________ | | |_______________________| + |XHCI HCD |<- | + |_________________________| | + + +SoC USB driver +============== +Structures +---------- +``struct snd_soc_usb`` + + - ``list``: list head for SND SoC struct list + - ``component``: reference to ASoC component + - ``connection_status_cb``: callback to notify connection events + - ``update_offload_route_info``: callback to fetch selected USB sound card/PCM + device + - ``priv_data``: driver data + +The snd_soc_usb structure can be referenced using the ASoC platform card +device, or a USB device (udev->dev). This is created by the ASoC BE DAI +link, and the USB sound entity will be able to pass information to the +ASoC BE DAI link using this structure. + +``struct snd_soc_usb_device`` + + - ``card_idx``: sound card index associated with USB sound device + - ``chip_idx``: USB sound chip array index + - ``cpcm_idx``: capture pcm device indexes associated with the USB sound device + - ``ppcm_idx``: playback pcm device indexes associated with the USB sound device + - ``num_playback``: number of playback streams + - ``num_capture``: number of capture streams + - ``list``: list head for the USB sound device list + +The struct snd_soc_usb_device is created by the USB sound offload driver. +This will carry basic parameters/limitations that will be used to +determine the possible offloading paths for this USB audio device. + +Functions +--------- +.. code-block:: rst + + int snd_soc_usb_find_supported_format(int card_idx, + struct snd_pcm_hw_params *params, int direction) +.. + + - ``card_idx``: the index into the USB sound chip array. + - ``params``: Requested PCM parameters from the USB DPCM BE DAI link + - ``direction``: capture or playback + +**snd_soc_usb_find_supported_format()** ensures that the requested audio profile +being requested by the external DSP is supported by the USB device. + +Returns 0 on success, and -EOPNOTSUPP on failure. + +.. code-block:: rst + + int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev) +.. + + - ``usbdev``: the usb device that was discovered + - ``sdev``: capabilities of the device + +**snd_soc_usb_connect()** notifies the ASoC USB DCPM BE DAI link of a USB +audio device detection. This can be utilized in the BE DAI +driver to keep track of available USB audio devices. This is intended +to be called by the USB offload driver residing in USB SND. + +Returns 0 on success, negative error code on failure. + +.. code-block:: rst + + int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev) +.. + + - ``usbdev``: the usb device that was removed + - ``sdev``: capabilities to free + +**snd_soc_usb_disconnect()** notifies the ASoC USB DCPM BE DAI link of a USB +audio device removal. This is intended to be called by the USB offload +driver that resides in USB SND. + +.. code-block:: rst + + void *snd_soc_usb_find_priv_data(struct device *usbdev) +.. + + - ``usbdev``: the usb device to reference to find private data + +**snd_soc_usb_find_priv_data()** fetches the private data saved to the SoC USB +device. + +Returns pointer to priv_data on success, NULL on failure. + +.. code-block:: rst + + int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack) +.. + + - ``component``: ASoC component to add the jack + - ``jack``: jack component to populate + +**snd_soc_usb_setup_offload_jack()** is a helper to add a sound jack control to +the platform sound card. This will allow for consistent naming to be used on +designs that support USB audio offloading. Additionally, this will enable the +jack to notify of changes. + +Returns 0 on success, negative otherwise. + +.. code-block:: rst + + int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route) +.. + + - ``dev``: USB device to look up offload path mapping + - ``card``: USB sound card index + - ``pcm``: USB sound PCM device index + - ``direction``: direction to fetch offload routing information + - ``path``: kcontrol selector - pcm device or card index + - ``route``: mapping of sound card and pcm indexes for the offload path. This is + an array of two integers that will carry the card and pcm device indexes + in that specific order. This can be used as the array for the kcontrol + output. + +**snd_soc_usb_update_offload_route()** calls a registered callback to the USB BE DAI +link to fetch the information about the mapped ASoC devices for executing USB audio +offload for the device. ``route`` may be a pointer to a kcontrol value output array, +which carries values when the kcontrol is read. + +Returns 0 on success, negative otherwise. + +.. code-block:: rst + + struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component, + void *data); +.. + + - ``component``: DPCM BE DAI link component + - ``data``: private data + +**snd_soc_usb_allocate_port()** allocates a SoC USB device and populates standard +parameters that is used for further operations. + +Returns a pointer to struct soc_usb on success, negative on error. + +.. code-block:: rst + + void snd_soc_usb_free_port(struct snd_soc_usb *usb); +.. + + - ``usb``: SoC USB device to free + +**snd_soc_usb_free_port()** frees a SoC USB device. + +.. code-block:: rst + + void snd_soc_usb_add_port(struct snd_soc_usb *usb); +.. + + - ``usb``: SoC USB device to add + +**snd_soc_usb_add_port()** add an allocated SoC USB device to the SOC USB framework. +Once added, this device can be referenced by further operations. + +.. code-block:: rst + + void snd_soc_usb_remove_port(struct snd_soc_usb *usb); +.. + + - ``usb``: SoC USB device to remove + +**snd_soc_usb_remove_port()** removes a SoC USB device from the SoC USB framework. +After removing a device, any SOC USB operations would not be able to reference the +device removed. + +How to Register to SoC USB +-------------------------- +The ASoC DPCM USB BE DAI link is the entity responsible for allocating and +registering the SoC USB device on the component bind. Likewise, it will +also be responsible for freeing the allocated resources. An example can +be shown below: + +.. code-block:: rst + + static int q6usb_component_probe(struct snd_soc_component *component) + { + ... + data->usb = snd_soc_usb_allocate_port(component, 1, &data->priv); + if (!data->usb) + return -ENOMEM; + + usb->connection_status_cb = q6usb_alsa_connection_cb; + + ret = snd_soc_usb_add_port(usb); + if (ret < 0) { + dev_err(component->dev, "failed to add usb port\n"); + goto free_usb; + } + ... + } + + static void q6usb_component_remove(struct snd_soc_component *component) + { + ... + snd_soc_usb_remove_port(data->usb); + snd_soc_usb_free_port(data->usb); + } + + static const struct snd_soc_component_driver q6usb_dai_component = { + .probe = q6usb_component_probe, + .remove = q6usb_component_remove, + .name = "q6usb-dai-component", + ... + }; +.. + +BE DAI links can pass along vendor specific information as part of the +call to allocate the SoC USB device. This will allow any BE DAI link +parameters or settings to be accessed by the USB offload driver that +resides in USB SND. + +USB Audio Device Connection Flow +-------------------------------- +USB devices can be hotplugged into the USB ports at any point in time. +The BE DAI link should be aware of the current state of the physical USB +port, i.e. if there are any USB devices with audio interface(s) connected. +connection_status_cb() can be used to notify the BE DAI link of any change. + +This is called whenever there is a USB SND interface bind or remove event, +using snd_soc_usb_connect() or snd_soc_usb_disconnect(): + +.. code-block:: rst + + static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip) + { + ... + snd_soc_usb_connect(usb_get_usb_backend(udev), sdev); + ... + } + + static void qc_usb_audio_offload_disconnect(struct snd_usb_audio *chip) + { + ... + snd_soc_usb_disconnect(usb_get_usb_backend(chip->dev), dev->sdev); + ... + } +.. + +In order to account for conditions where driver or device existence is +not guaranteed, USB SND exposes snd_usb_rediscover_devices() to resend the +connect events for any identified USB audio interfaces. Consider the +the following situation: + + **usb_audio_probe()** + | --> USB audio streams allocated and saved to usb_chip[] + | --> Propagate connect event to USB offload driver in USB SND + | --> **snd_soc_usb_connect()** exits as USB BE DAI link is not ready + + BE DAI link component probe + | --> DAI link is probed and SoC USB port is allocated + | --> The USB audio device connect event is missed + +To ensure connection events are not missed, **snd_usb_rediscover_devices()** +is executed when the SoC USB device is registered. Now, when the BE DAI +link component probe occurs, the following highlights the sequence: + + BE DAI link component probe + | --> DAI link is probed and SoC USB port is allocated + | --> SoC USB device added, and **snd_usb_rediscover_devices()** runs + + **snd_usb_rediscover_devices()** + | --> Traverses through usb_chip[] and for non-NULL entries issue + | **connection_status_cb()** + +In the case where the USB offload driver is unbound, while USB SND is ready, +the **snd_usb_rediscover_devices()** is called during module init. This allows +for the offloading path to also be enabled with the following flow: + + **usb_audio_probe()** + | --> USB audio streams allocated and saved to usb_chip[] + | --> Propagate connect event to USB offload driver in USB SND + | --> USB offload driver **NOT** ready! + + BE DAI link component probe + | --> DAI link is probed and SoC USB port is allocated + | --> No USB connect event due to missing USB offload driver + + USB offload driver probe + | --> **qc_usb_audio_offload_init()** + | --> Calls **snd_usb_rediscover_devices()** to notify of devices + +USB Offload Related Kcontrols +============================= +Details +------- +A set of kcontrols can be utilized by applications to help select the proper sound +devices to enable USB audio offloading. SoC USB exposes the get_offload_dev() +callback that designs can use to ensure that the proper indices are returned to the +application. + +Implementation +-------------- + +**Example:** + + **Sound Cards**: + + :: + + 0 [SM8250MTPWCD938]: sm8250 - SM8250-MTP-WCD9380-WSA8810-VA-D + SM8250-MTP-WCD9380-WSA8810-VA-DMIC + 1 [Seri ]: USB-Audio - Plantronics Blackwire 3225 Seri + Plantronics Plantronics Blackwire + 3225 Seri at usb-xhci-hcd.1.auto-1.1, + full sp + 2 [C320M ]: USB-Audio - Plantronics C320-M + Plantronics Plantronics C320-M at usb-xhci-hcd.1.auto-1.2, full speed + + **PCM Devices**: + + :: + + card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 0: MultiMedia1 (*) [] + Subdevices: 1/1 + Subdevice #0: subdevice #0 + card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 1: MultiMedia2 (*) [] + Subdevices: 1/1 + Subdevice #0: subdevice #0 + card 1: Seri [Plantronics Blackwire 3225 Seri], device 0: USB Audio [USB Audio] + Subdevices: 1/1 + Subdevice #0: subdevice #0 + card 2: C320M [Plantronics C320-M], device 0: USB Audio [USB Audio] + Subdevices: 1/1 + Subdevice #0: subdevice #0 + + **USB Sound Card** - card#1: + + :: + + USB Offload Playback Card Route PCM#0 -1 (range -1->32) + USB Offload Playback PCM Route PCM#0 -1 (range -1->255) + + **USB Sound Card** - card#2: + + :: + + USB Offload Playback Card Route PCM#0 0 (range -1->32) + USB Offload Playback PCM Route PCM#0 1 (range -1->255) + +The above example shows a scenario where the system has one ASoC platform card +(card#0) and two USB sound devices connected (card#1 and card#2). When reading +the available kcontrols for each USB audio device, the following kcontrols lists +the mapped offload card and pcm device indexes for the specific USB device: + + ``USB Offload Playback Card Route PCM#*`` + + ``USB Offload Playback PCM Route PCM#*`` + +The kcontrol is indexed, because a USB audio device could potentially have +several PCM devices. The above kcontrols are defined as: + + - ``USB Offload Playback Card Route PCM#`` **(R)**: Returns the ASoC platform sound + card index for a mapped offload path. The output **"0"** (card index) signifies + that there is an available offload path for the USB SND device through card#0. + If **"-1"** is seen, then no offload path is available for the USB SND device. + This kcontrol exists for each USB audio device that exists in the system, and + its expected to derive the current status of offload based on the output value + for the kcontrol along with the PCM route kcontrol. + + - ``USB Offload Playback PCM Route PCM#`` **(R)**: Returns the ASoC platform sound + PCM device index for a mapped offload path. The output **"1"** (PCM device index) + signifies that there is an available offload path for the USB SND device through + PCM device#0. If **"-1"** is seen, then no offload path is available for the USB\ + SND device. This kcontrol exists for each USB audio device that exists in the + system, and its expected to derive the current status of offload based on the + output value for this kcontrol, in addition to the card route kcontrol. + +USB Offload Playback Route Kcontrol +----------------------------------- +In order to allow for vendor specific implementations on audio offloading device +selection, the SoC USB layer exposes the following: + +.. code-block:: rst + + int (*update_offload_route_info)(struct snd_soc_component *component, + int card, int pcm, int direction, + enum snd_soc_usb_kctl path, + long *route) +.. + +These are specific for the **USB Offload Playback Card Route PCM#** and **USB +Offload PCM Route PCM#** kcontrols. + +When users issue get calls to the kcontrol, the registered SoC USB callbacks will +execute the registered function calls to the DPCM BE DAI link. + +**Callback Registration:** + +.. code-block:: rst + + static int q6usb_component_probe(struct snd_soc_component *component) + { + ... + usb = snd_soc_usb_allocate_port(component, 1, &data->priv); + if (IS_ERR(usb)) + return -ENOMEM; + + usb->connection_status_cb = q6usb_alsa_connection_cb; + usb->update_offload_route_info = q6usb_get_offload_dev; + + ret = snd_soc_usb_add_port(usb); +.. + +Existing USB Sound Kcontrol +--------------------------- +With the introduction of USB offload support, the above USB offload kcontrol +will be added to the pre existing list of kcontrols identified by the USB sound +framework. These kcontrols are still the main controls that are used to +modify characteristics pertaining to the USB audio device. + + :: + + Number of controls: 9 + ctl type num name value + 0 INT 2 Capture Channel Map 0, 0 (range 0->36) + 1 INT 2 Playback Channel Map 0, 0 (range 0->36) + 2 BOOL 1 Headset Capture Switch On + 3 INT 1 Headset Capture Volume 10 (range 0->13) + 4 BOOL 1 Sidetone Playback Switch On + 5 INT 1 Sidetone Playback Volume 4096 (range 0->8192) + 6 BOOL 1 Headset Playback Switch On + 7 INT 2 Headset Playback Volume 20, 20 (range 0->24) + 8 INT 1 USB Offload Playback Card Route PCM#0 0 (range -1->32) + 9 INT 1 USB Offload Playback PCM Route PCM#0 1 (range -1->255) + +Since USB audio device controls are handled over the USB control endpoint, use the +existing mechanisms present in the USB mixer to set parameters, such as volume. From patchwork Thu Jan 16 23:28:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858134 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1C4B242260; Thu, 16 Jan 2025 23:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; cv=none; b=sYv+3FZqADFgwzRxCQfkdy2UfZ2v874jvZWjub1eKkaCLBxzWDGE4aZtAM7EXsHmy04F4AdzQBmyqYIwvuP8uj8kiZL5n9ChbuOrsVbJZX+axJNZlE/QVj4ftetTceNIUl/VTsyCAAbAxZ8cq3pTv8vuOzXC3qZ7onMdK1ivHIU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; c=relaxed/simple; bh=TOF3rbh5SP8regoKVCofHUubqKWFiFWZ68gGRXvrCKw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tPsEIN++Cav1MeOKewODq6+JjsKmqn7zbc6vxLiwzpGuGguk4ry27VdeGsR7DepzUVUfqSra+PH1SwbuzBaxsofgM9j7GfVFG1Uz9RQs/cuUJdmEqgeBeY7N+h6NuL1JlX0y2N3o5hMYcGz2Fhklp63cR9Tr6DLTc3mERYI/rFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=LcPnD9ll; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="LcPnD9ll" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN7kVv011365; Thu, 16 Jan 2025 23:28:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= FW5leIr9BjL8euqPM4EDkDOLWlrjKmn7lR0gHyi0sJw=; b=LcPnD9llu6WrnD04 54Lw6cHLufUegibxC5HmVuX6Tyg9eIoi/l+GcoEHeRegXDnpNarAGdNSCwxDSMZa F9jRWNZyabvp7LhLhp7m3rKZdLfdyUPUk3ipUIJCipP7Lt2DH4QAoyQYehZ4aCbh McJg2rjur4UOWWaGlpUBOec+C4jDgETUePuqwBwSiMuRFEpvRLl/uSotaDsh9hIN OGRfw3JeqwziivrxouB6HGJH8I8VC27bNfhl8YGJupZA8zYIiD+qR2kpVl/QcQG1 MGGV3Wv7SOCLETNdpeBgLWjszkHH8u8rPE6t9qk5FGXc8cQNbr0wNMQqxnxn9pNo pujOgQ== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:49 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSmHP031847 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:48 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:47 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 24/31] ASoC: qcom: qdsp6: Add USB backend ASoC driver for Q6 Date: Thu, 16 Jan 2025 15:28:17 -0800 Message-ID: <20250116232824.3748438-25-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 0BHdXOMjovas976IXkii_gIzMkEzUdLS X-Proofpoint-ORIG-GUID: 0BHdXOMjovas976IXkii_gIzMkEzUdLS X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 Create a USB BE component that will register a new USB port to the ASoC USB framework. This will handle determination on if the requested audio profile is supported by the USB device currently selected. Check for if the PCM format is supported during the hw_params callback. If the profile is not supported then the userspace ALSA entity will receive an error, and can take further action. Signed-off-by: Wesley Cheng --- include/sound/q6usboffload.h | 20 +++ sound/soc/qcom/Kconfig | 10 ++ sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6usb.c | 246 ++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 include/sound/q6usboffload.h create mode 100644 sound/soc/qcom/qdsp6/q6usb.c diff --git a/include/sound/q6usboffload.h b/include/sound/q6usboffload.h new file mode 100644 index 000000000000..cca6d353afc3 --- /dev/null +++ b/include/sound/q6usboffload.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * sound/q6usboffload.h -- QDSP6 USB offload + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/** + * struct q6usb_offload + * @dev - dev handle to usb be + * @domain - allocated iommu domain + * @sid - streamID for iommu + * @intr_num - usb interrupter number + **/ +struct q6usb_offload { + struct device *dev; + struct iommu_domain *domain; + long long sid; + u16 intr_num; +}; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index ca7a30ebd26a..77c21fc4fc1b 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -118,6 +118,16 @@ config SND_SOC_QDSP6_PRM tristate select SND_SOC_QDSP6_PRM_LPASS_CLOCKS +config SND_SOC_QDSP6_USB + tristate "SoC ALSA USB offloading backing for QDSP6" + depends on SND_SOC_USB + help + Adds support for USB offloading for QDSP6 ASoC + based platform sound cards. This will enable the + Q6USB DPCM backend DAI link, which will interact + with the SoC USB framework to initialize a session + with active USB SND devices. + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 26b7c55c9c11..67267304e7e9 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_SND_SOC_QDSP6_APM_DAI) += q6apm-dai.o obj-$(CONFIG_SND_SOC_QDSP6_APM_LPASS_DAI) += q6apm-lpass-dais.o obj-$(CONFIG_SND_SOC_QDSP6_PRM) += q6prm.o obj-$(CONFIG_SND_SOC_QDSP6_PRM_LPASS_CLOCKS) += q6prm-clocks.o +obj-$(CONFIG_SND_SOC_QDSP6_USB) += q6usb.o diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c new file mode 100644 index 000000000000..d57bdc722897 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "q6afe.h" +#include "q6dsp-lpass-ports.h" + +#define Q6_USB_SID_MASK 0xF + +struct q6usb_port_data { + struct q6afe_usb_cfg usb_cfg; + struct snd_soc_usb *usb; + struct q6usb_offload priv; + + /* Protects against operations between SOC USB and ASoC */ + struct mutex mutex; + struct list_head devices; +}; + +static const struct snd_soc_dapm_widget q6usb_dai_widgets[] = { + SND_SOC_DAPM_HP("USB_RX_BE", NULL), +}; + +static const struct snd_soc_dapm_route q6usb_dapm_routes[] = { + {"USB Playback", NULL, "USB_RX_BE"}, +}; + +static int q6usb_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct q6usb_port_data *data = dev_get_drvdata(dai->dev); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int direction = substream->stream; + struct q6afe_port *q6usb_afe; + struct snd_soc_usb_device *sdev; + int ret = -EINVAL; + + mutex_lock(&data->mutex); + + /* No active chip index */ + if (list_empty(&data->devices)) + goto out; + + sdev = list_last_entry(&data->devices, struct snd_soc_usb_device, list); + + ret = snd_soc_usb_find_supported_format(sdev->chip_idx, params, direction); + if (ret < 0) + goto out; + + q6usb_afe = q6afe_port_get_from_id(cpu_dai->dev, USB_RX); + if (IS_ERR(q6usb_afe)) + goto out; + + /* Notify audio DSP about the devices being offloaded */ + ret = afe_port_send_usb_dev_param(q6usb_afe, sdev->card_idx, + sdev->ppcm_idx[sdev->num_playback - 1]); + +out: + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct snd_soc_dai_ops q6usb_ops = { + .hw_params = q6usb_hw_params, +}; + +static struct snd_soc_dai_driver q6usb_be_dais[] = { + { + .playback = { + .stream_name = "USB BE RX", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | + SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE, + .channels_min = 1, + .channels_max = 2, + .rate_max = 192000, + .rate_min = 8000, + }, + .id = USB_RX, + .name = "USB_RX_BE", + .ops = &q6usb_ops, + }, +}; + +static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + int id = args->args[0]; + int ret = -EINVAL; + int i; + + for (i = 0; i < ARRAY_SIZE(q6usb_be_dais); i++) { + if (q6usb_be_dais[i].id == id) { + *dai_name = q6usb_be_dais[i].name; + ret = 0; + break; + } + } + + return ret; +} + +static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, + struct snd_soc_usb_device *sdev, bool connected) +{ + struct q6usb_port_data *data; + + if (!usb->component) + return -ENODEV; + + data = dev_get_drvdata(usb->component->dev); + + mutex_lock(&data->mutex); + if (connected) { + /* Selects the latest USB headset plugged in for offloading */ + list_add_tail(&sdev->list, &data->devices); + } else { + list_del(&sdev->list); + } + mutex_unlock(&data->mutex); + + return 0; +} + +static int q6usb_component_probe(struct snd_soc_component *component) +{ + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + struct snd_soc_usb *usb; + + usb = snd_soc_usb_allocate_port(component, &data->priv); + if (IS_ERR(usb)) + return -ENOMEM; + + usb->connection_status_cb = q6usb_alsa_connection_cb; + + snd_soc_usb_add_port(usb); + data->usb = usb; + + return 0; +} + +static void q6usb_component_remove(struct snd_soc_component *component) +{ + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + + snd_soc_usb_remove_port(data->usb); + snd_soc_usb_free_port(data->usb); +} + +static const struct snd_soc_component_driver q6usb_dai_component = { + .probe = q6usb_component_probe, + .remove = q6usb_component_remove, + .name = "q6usb-dai-component", + .dapm_widgets = q6usb_dai_widgets, + .num_dapm_widgets = ARRAY_SIZE(q6usb_dai_widgets), + .dapm_routes = q6usb_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(q6usb_dapm_routes), + .of_xlate_dai_name = q6usb_audio_ports_of_xlate_dai_name, +}; + +static int q6usb_dai_dev_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct q6usb_port_data *data; + struct device *dev = &pdev->dev; + struct of_phandle_args args; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_property_read_u16(node, "qcom,usb-audio-intr-idx", + &data->priv.intr_num); + if (ret) { + dev_err(&pdev->dev, "failed to read intr idx.\n"); + return ret; + } + + ret = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); + if (ret < 0) + data->priv.sid = -1; + else + data->priv.sid = args.args[0] & Q6_USB_SID_MASK; + + data->priv.domain = iommu_get_domain_for_dev(&pdev->dev); + + data->priv.dev = dev; + INIT_LIST_HEAD(&data->devices); + dev_set_drvdata(dev, data); + + return devm_snd_soc_register_component(dev, &q6usb_dai_component, + q6usb_be_dais, ARRAY_SIZE(q6usb_be_dais)); +} + +static const struct of_device_id q6usb_dai_device_id[] = { + { .compatible = "qcom,q6usb" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6usb_dai_device_id); + +static struct platform_driver q6usb_dai_platform_driver = { + .driver = { + .name = "q6usb-dai", + .of_match_table = of_match_ptr(q6usb_dai_device_id), + }, + .probe = q6usb_dai_dev_probe, + /* + * Remove not required as resources are cleaned up as part of + * component removal. Others are device managed resources. + */ +}; +module_platform_driver(q6usb_dai_platform_driver); + +MODULE_DESCRIPTION("Q6 USB backend dai driver"); +MODULE_LICENSE("GPL"); From patchwork Thu Jan 16 23:28:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858129 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2D401F3FDC; Thu, 16 Jan 2025 23:29:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070150; cv=none; b=lkoapuhR5aM5J01GJ29iVYDeXfrSv6duIUfjkChr/kNGEPCvElSXehXyFw5dnUq+ndCrALTezgbKD+O+8VnLeiIFN84e23fULcVj92RQ5PEdNTs9UcFIw4eUQrjJKIhj2GuUJTobsvBK6+lzH/3fm9X3w3i5v/rJSCEmCQww+u0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070150; c=relaxed/simple; bh=Q2L1I6iK7YTOa5bY3EDQkwKaS08GfozKSfSy79jH0y0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hKwy3u0S9h1TFTRjMP7eZJPUZfcTEnOBk8EaC/iYyi42UiZDDLvGQGgUyN/DVnB0A9zaPDUYEAwQClIonr3dx7OfIvhzi3tvc7RaQ5ew3V3xIRfbbGdb981buamhO7U33VfYU5QF5xpho4JbrUZjG22OWPCYCAG2cTmVGhO629Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=IggloN4Q; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="IggloN4Q" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GN91Lm013903; Thu, 16 Jan 2025 23:28:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= urxZLdtpB4bVF6l5A9aDHfrtDSmQQC9rekGWIrKpX9g=; b=IggloN4QoJKfkyrf CPXRDqKjLctFhDOjnbA26mxmpjqo4I34wXROHhQkhfHxfJjeWtPKQvSVhrYwUOG4 ow0WRqCJcfbBmxxnLhYuCGjUBg9EHS839b0OzT3Eox7hNesW0e/THveuXwGMY1R+ tSBZQNqJcgnXS8NL2K75xJRbxRa0asDbdTJzHmdikO4ZDIlMuenwPvEI2NCL6Ybh SyfvkpKIeUG2MF4p6nABvRMAQPjgqZHkV90QcxBPIciyROEVljozQVKslWNbnlOE MpW8q9kBGwqY0sm1o6kkA8ssoZCiKJDxH+mLTCF0fKdJFbJ5hN1S2SccvyR6ZBUQ eT4I2Q== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 447bgw810v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:49 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSmk9019339 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:48 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:47 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 25/31] ASoC: qcom: qdsp6: Add headphone jack for offload connection status Date: Thu, 16 Jan 2025 15:28:18 -0800 Message-ID: <20250116232824.3748438-26-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 1EJp4qsnlUxSxNZYo685p8nuh1ZQGsju X-Proofpoint-ORIG-GUID: 1EJp4qsnlUxSxNZYo685p8nuh1ZQGsju X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 bulkscore=0 mlxscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 The headphone jack framework has a well defined infrastructure for notifying userspace entities through input devices. Expose a jack device that carries information about if an offload capable device is connected. Applications can further identify specific offloading information through other SND kcontrols. Signed-off-by: Wesley Cheng --- sound/soc/qcom/Kconfig | 5 +++ sound/soc/qcom/Makefile | 2 ++ sound/soc/qcom/qdsp6/q6usb.c | 41 ++++++++++++++++++++++ sound/soc/qcom/sm8250.c | 24 ++++++++++++- sound/soc/qcom/usb_offload_utils.c | 56 ++++++++++++++++++++++++++++++ sound/soc/qcom/usb_offload_utils.h | 30 ++++++++++++++++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 sound/soc/qcom/usb_offload_utils.c create mode 100644 sound/soc/qcom/usb_offload_utils.h diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 77c21fc4fc1b..6bedac2effc9 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -118,9 +118,14 @@ config SND_SOC_QDSP6_PRM tristate select SND_SOC_QDSP6_PRM_LPASS_CLOCKS +config SND_SOC_QCOM_OFFLOAD_UTILS + tristate + config SND_SOC_QDSP6_USB tristate "SoC ALSA USB offloading backing for QDSP6" depends on SND_SOC_USB + select SND_SOC_QCOM_OFFLOAD_UTILS + help Adds support for USB offloading for QDSP6 ASoC based platform sound cards. This will enable the diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 16db7b53ddac..985ce2ae286b 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -30,6 +30,7 @@ snd-soc-sc8280xp-y := sc8280xp.o snd-soc-qcom-common-y := common.o snd-soc-qcom-sdw-y := sdw.o snd-soc-x1e80100-y := x1e80100.o +snd-soc-qcom-offload-utils-objs := usb_offload_utils.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o @@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_SM8250) += snd-soc-sm8250.o obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o obj-$(CONFIG_SND_SOC_X1E80100) += snd-soc-x1e80100.o +obj-$(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) += snd-soc-qcom-offload-utils.o #DSP lib obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/ diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index d57bdc722897..d3698dcecca0 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ struct q6usb_port_data { struct q6afe_usb_cfg usb_cfg; struct snd_soc_usb *usb; + struct snd_soc_jack *hs_jack; struct q6usb_offload priv; /* Protects against operations between SOC USB and ASoC */ @@ -142,16 +144,54 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, mutex_lock(&data->mutex); if (connected) { + if (data->hs_jack) + snd_jack_report(data->hs_jack->jack, SND_JACK_USB); + /* Selects the latest USB headset plugged in for offloading */ list_add_tail(&sdev->list, &data->devices); } else { list_del(&sdev->list); + + if (data->hs_jack) + snd_jack_report(data->hs_jack->jack, 0); } mutex_unlock(&data->mutex); return 0; } +static void q6usb_component_disable_jack(struct q6usb_port_data *data) +{ + /* Offload jack has already been disabled */ + if (!data->hs_jack) + return; + + snd_jack_report(data->hs_jack->jack, 0); + data->hs_jack = NULL; +} + +static void q6usb_component_enable_jack(struct q6usb_port_data *data, + struct snd_soc_jack *jack) +{ + snd_jack_report(jack->jack, !list_empty(&data->devices) ? SND_JACK_USB : 0); + data->hs_jack = jack; +} + +static int q6usb_component_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *priv) +{ + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + + mutex_lock(&data->mutex); + if (jack) + q6usb_component_enable_jack(data, jack); + else + q6usb_component_disable_jack(data); + mutex_unlock(&data->mutex); + + return 0; +} + static int q6usb_component_probe(struct snd_soc_component *component) { struct q6usb_port_data *data = dev_get_drvdata(component->dev); @@ -179,6 +219,7 @@ static void q6usb_component_remove(struct snd_soc_component *component) static const struct snd_soc_component_driver q6usb_dai_component = { .probe = q6usb_component_probe, + .set_jack = q6usb_component_set_jack, .remove = q6usb_component_remove, .name = "q6usb-dai-component", .dapm_widgets = q6usb_dai_widgets, diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index 45e0c33fc3f3..774e3aa3d1a4 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -12,6 +12,7 @@ #include #include "qdsp6/q6afe.h" #include "common.h" +#include "usb_offload_utils.h" #include "sdw.h" #define DRIVER_NAME "sm8250" @@ -22,14 +23,34 @@ struct sm8250_snd_data { struct snd_soc_card *card; struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; struct snd_soc_jack jack; + struct snd_soc_jack usb_offload_jack; + bool usb_offload_jack_setup; bool jack_setup; }; static int sm8250_snd_init(struct snd_soc_pcm_runtime *rtd) { struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int ret; + + if (cpu_dai->id == USB_RX) + ret = qcom_snd_usb_offload_jack_setup(rtd, &data->usb_offload_jack, + &data->usb_offload_jack_setup); + else + ret = qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); + return ret; +} + +static void sm8250_snd_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + + if (cpu_dai->id == USB_RX) + qcom_snd_usb_offload_jack_remove(rtd, + &data->usb_offload_jack_setup); - return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, @@ -145,6 +166,7 @@ static void sm8250_add_be_ops(struct snd_soc_card *card) for_each_card_prelinks(card, i, link) { if (link->no_pcm == 1) { link->init = sm8250_snd_init; + link->exit = sm8250_snd_exit; link->be_hw_params_fixup = sm8250_be_hw_params_fixup; link->ops = &sm8250_be_ops; } diff --git a/sound/soc/qcom/usb_offload_utils.c b/sound/soc/qcom/usb_offload_utils.c new file mode 100644 index 000000000000..0a24b278fcdf --- /dev/null +++ b/sound/soc/qcom/usb_offload_utils.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include + +#include "usb_offload_utils.h" + +int qcom_snd_usb_offload_jack_setup(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_jack *jack, bool *jack_setup) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + int ret = 0; + + if (cpu_dai->id != USB_RX) + return -EINVAL; + + if (!*jack_setup) { + ret = snd_soc_usb_setup_offload_jack(codec_dai->component, jack); + if (ret) + return ret; + } + + *jack_setup = true; + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_snd_usb_offload_jack_setup); + +int qcom_snd_usb_offload_jack_remove(struct snd_soc_pcm_runtime *rtd, + bool *jack_setup) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + int ret = 0; + + if (cpu_dai->id != USB_RX) + return -EINVAL; + + if (*jack_setup) { + ret = snd_soc_component_set_jack(codec_dai->component, NULL, NULL); + if (ret) + return ret; + } + + *jack_setup = false; + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_snd_usb_offload_jack_remove); +MODULE_DESCRIPTION("ASoC Q6 USB offload controls"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/usb_offload_utils.h b/sound/soc/qcom/usb_offload_utils.h new file mode 100644 index 000000000000..c3f411f565b0 --- /dev/null +++ b/sound/soc/qcom/usb_offload_utils.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#ifndef __QCOM_SND_USB_OFFLOAD_UTILS_H__ +#define __QCOM_SND_USB_OFFLOAD_UTILS_H__ + +#include + +#if IS_ENABLED(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) +int qcom_snd_usb_offload_jack_setup(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_jack *jack, bool *jack_setup); + +int qcom_snd_usb_offload_jack_remove(struct snd_soc_pcm_runtime *rtd, + bool *jack_setup); +#else +static inline int qcom_snd_usb_offload_jack_setup(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_jack *jack, + bool *jack_setup) +{ + return -ENODEV; +} + +static inline int qcom_snd_usb_offload_jack_remove(struct snd_soc_pcm_runtime *rtd, + bool *jack_setup) +{ + return -ENODEV; +} +#endif /* IS_ENABLED(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) */ +#endif /* __QCOM_SND_USB_OFFLOAD_UTILS_H__ */ From patchwork Thu Jan 16 23:28:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858126 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 240AA24E686; Thu, 16 Jan 2025 23:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070157; cv=none; b=c8d5QhUWYrPA2arnT1xlJn9d4G88EpbovyBa8FyuRnYU0XPa9w/2Ivw6U37Lz11U+ezoE9DSOhsMSvLRumKKr2I6+xfe2p6Kv4oCFAaFcDhw732QMUv9eaBvihR+p8NIE2QkbrxgyFa9ooiX+uY+BFx3wI32L7hiQ1JY9uBroKU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070157; c=relaxed/simple; bh=3QFTum6b6TYkCsoCbA8ri0iL95hPrcAGFqDlRqu9AZ8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cKBrJeaau+v32IEQjr/JUZNGEK8zC418I45ZZcrqmNnPS36PmYMPEXaY8Jy0a8g7b0Y9+TBIxev141Vw0MU1ZGAg6op8SvDk8NYtVLe+r/M39iFn2+gofhlOj2bHDpoLEh4ZW2/jlpcHm3LnhXwYZxJMCw2dsZHfeHU/AH/WUWM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=jhBcmtJo; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="jhBcmtJo" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GEK2vi017111; Thu, 16 Jan 2025 23:28:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= tHOjyOXhTDWn+i/TaTd9A+AO+bPk4LxFuw8J0AV0EqA=; b=jhBcmtJo+rx0DJnp da92fX7HG9LIZ1HX++gB56nRWElT3KI76p0CzWtEu9Fuffblr3JAPvtvIAEKixS2 UIkVu6lw+Pb8fhk9UFbIGUbVnaZqBIZjy+QXkc4kTbsAb18spb5fCVOQ73CLLOAp HdGc9ftT0c98sYvWrB0GhdGrr9+k8I480ceMCx68b7QOICtlQT+Ed3r+CdjpvgWu QSCGd8xVNu6kQNc+37cuKxzU4uFtCgKMYZRccEoyvrAIAj5gFxTNriTUELLg/jPx DrGkTI84Ac3sdZ36CwmtptC3d60mIuq6ABFRpuQs+xWvDxuJgT1/ha30LAgRzrJ2 /wCYRA== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473se17f2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:50 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSn2E019388 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:49 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:48 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 27/31] ALSA: usb-audio: qcom: Add USB QMI definitions Date: Thu, 16 Jan 2025 15:28:20 -0800 Message-ID: <20250116232824.3748438-28-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: bM6QpN0DmiEjpCTnoh-4fjVbmaic9GX9 X-Proofpoint-ORIG-GUID: bM6QpN0DmiEjpCTnoh-4fjVbmaic9GX9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 spamscore=0 adultscore=0 mlxscore=0 bulkscore=0 impostorscore=0 malwarescore=0 suspectscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 The Qualcomm USB audio offload driver utilizes the QMI protocol to communicate with the audio DSP. Add the necessary QMI header and field definitions, so the QMI interface driver is able to route the QMI packet received to the USB audio offload driver. Signed-off-by: Wesley Cheng --- sound/usb/qcom/usb_audio_qmi_v01.c | 863 +++++++++++++++++++++++++++++ sound/usb/qcom/usb_audio_qmi_v01.h | 164 ++++++ 2 files changed, 1027 insertions(+) create mode 100644 sound/usb/qcom/usb_audio_qmi_v01.c create mode 100644 sound/usb/qcom/usb_audio_qmi_v01.h diff --git a/sound/usb/qcom/usb_audio_qmi_v01.c b/sound/usb/qcom/usb_audio_qmi_v01.c new file mode 100644 index 000000000000..151ae7b591de --- /dev/null +++ b/sound/usb/qcom/usb_audio_qmi_v01.c @@ -0,0 +1,863 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include + +#include "usb_audio_qmi_v01.h" + +static const 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 const 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 const 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 const 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, + }, +}; + +const 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, + }, +}; + +const 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_qmi_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_qmi_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, + }, +}; + +const 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_qmi_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, + }, +}; diff --git a/sound/usb/qcom/usb_audio_qmi_v01.h b/sound/usb/qcom/usb_audio_qmi_v01.h new file mode 100644 index 000000000000..f2563537ed40 --- /dev/null +++ b/sound/usb/qcom/usb_audio_qmi_v01.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022-2025 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_qmi_audio_stream_status_enum_v01 { + USB_QMI_STREAM_STATUS_ENUM_MIN_VAL_V01 = INT_MIN, + USB_QMI_STREAM_REQ_SUCCESS_V01 = 0, + USB_QMI_STREAM_REQ_FAILURE_V01 = 1, + USB_QMI_STREAM_REQ_FAILURE_NOT_FOUND_V01 = 2, + USB_QMI_STREAM_REQ_FAILURE_INVALID_PARAM_V01 = 3, + USB_QMI_STREAM_REQ_FAILURE_MEMALLOC_V01 = 4, + USB_QMI_STREAM_STATUS_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum usb_qmi_audio_device_indication_enum_v01 { + USB_QMI_DEVICE_INDICATION_ENUM_MIN_VAL_V01 = INT_MIN, + USB_QMI_DEV_CONNECT_V01 = 0, + USB_QMI_DEV_DISCONNECT_V01 = 1, + USB_QMI_DEV_SUSPEND_V01 = 2, + USB_QMI_DEV_RESUME_V01 = 3, + USB_QMI_DEVICE_INDICATION_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum usb_qmi_audio_device_speed_enum_v01 { + USB_QMI_DEVICE_SPEED_ENUM_MIN_VAL_V01 = INT_MIN, + USB_QMI_DEVICE_SPEED_INVALID_V01 = 0, + USB_QMI_DEVICE_SPEED_LOW_V01 = 1, + USB_QMI_DEVICE_SPEED_FULL_V01 = 2, + USB_QMI_DEVICE_SPEED_HIGH_V01 = 3, + USB_QMI_DEVICE_SPEED_SUPER_V01 = 4, + USB_QMI_DEVICE_SPEED_SUPER_PLUS_V01 = 5, + USB_QMI_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 const 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_qmi_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_qmi_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 const struct qmi_elem_info qmi_uaudio_stream_resp_msg_v01_ei[]; + +struct qmi_uaudio_stream_ind_msg_v01 { + enum usb_qmi_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 const struct qmi_elem_info qmi_uaudio_stream_ind_msg_v01_ei[]; + +#endif From patchwork Thu Jan 16 23:28:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858135 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C047B242240; Thu, 16 Jan 2025 23:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; cv=none; b=IWaL2IE4PT5rjgfB+FAUYgzjFSsGDgj4r4hRvsPJ1iJNxy9+9Garm/bz6LsVwM2BjH3KtRp0VsLnl8XmjEf3w8Zg4waJgomNQmHrgmUpPe2TKRJ8FqsOiAxeoyW0BLlCD5fRTqdzvUHCCi/zalq6EjS7skJ2c3G2nvyMav/YKj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070145; c=relaxed/simple; bh=e0b2PMzK8NYYjDj9J9K49pCUTLE1UbAYCdcTqLGT8Ug=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TLpuPwTfocrQQXvmwmcCTh9D7Pftdb3UCrAlSxITvUgZ3BQI04tho+kFJqZSWcwwgOiyAowrQ0xBSN040lM2tuzNwhqwnnb9yEItlbR8einRI1Pf9/LXmaMpsbesvAk6PFLtINcZqv3VqN0VSY06yA1Lh8tDGIWsMSVy8rDbs/k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ohzo6O7R; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ohzo6O7R" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GDraOp031335; Thu, 16 Jan 2025 23:28:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= HuQjQvgTorJQP6w/SA0f4gFZmlLi3n9LWXSiqv6lNqA=; b=ohzo6O7RoJN4aTxK 23B2Ps5u9yu3xBmdXMUAJ4JebaJU8y0NtnAdSIj3O/G5Ey+mfjAZ6t8ywcS5mpcH eI5E5AKKigSTd82PjRws7Pil4FjHHGx5BYWzE83NhwXUEp5cqaInliDlSI/boMiu NiGiwdPIzqVB3ZbxLNAbjF9mTjv0Rs7ekV+5JuJADizBnyeIS4/Uk+FJhdeP1knD 3TZt4AinxN/Xhn+dmfty6VBnqXEl2Xm9TTjhOEHe0nPbb8BJnxdqGyZbcYR62G3f TYaGK73jit4CTYPfNyleHxOLfty6NvsuZfazraHrVsOkYyBVGsKB69ZEPPnFi9WW Jjq9Ig== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473d7h8kr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:50 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSnIK022830 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:49 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:49 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 29/31] ALSA: usb-audio: qcom: Don't allow USB offload path if PCM device is in use Date: Thu, 16 Jan 2025 15:28:22 -0800 Message-ID: <20250116232824.3748438-30-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: VPjdQp7tL9sGmqSbWPniwibmcZ-23U5o X-Proofpoint-GUID: VPjdQp7tL9sGmqSbWPniwibmcZ-23U5o X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 clxscore=1015 adultscore=0 phishscore=0 impostorscore=0 bulkscore=0 spamscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=988 suspectscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160173 Add proper checks and updates to the USB substream once receiving a USB QMI stream enable request. If the substream is already in use from the non offload path, reject the stream enable request. In addition, update the USB substream opened parameter when enabling the offload path, so the non offload path can be blocked. Signed-off-by: Wesley Cheng --- sound/usb/qcom/qc_audio_offload.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 033e343ca0a0..29302446e9da 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1582,12 +1582,17 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, goto response; } + mutex_lock(&chip->mutex); if (req_msg->enable) { - if (info_idx < 0 || chip->system_suspend) { + if (info_idx < 0 || chip->system_suspend || subs->opened) { ret = -EBUSY; + mutex_unlock(&chip->mutex); + goto response; } + subs->opened = 1; } + mutex_unlock(&chip->mutex); if (req_msg->service_interval_valid) { ret = get_data_interval_from_si(subs, @@ -1609,6 +1614,11 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, if (!ret) ret = prepare_qmi_response(subs, req_msg, &resp, info_idx); + if (ret < 0) { + mutex_lock(&chip->mutex); + subs->opened = 0; + mutex_unlock(&chip->mutex); + } } else { info = &uadev[pcm_card_num].info[info_idx]; if (info->data_ep_pipe) { @@ -1638,6 +1648,9 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, } disable_audio_stream(subs); + mutex_lock(&chip->mutex); + subs->opened = 0; + mutex_unlock(&chip->mutex); } response: From patchwork Thu Jan 16 23:28:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858128 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 063EA1F561C; Thu, 16 Jan 2025 23:29:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070151; cv=none; b=m3EHZDcsaEyJG1poooxrMuRAdN+YmJTLXJ17I+zuN/PBgNTACRVW7TGCqYjReXSAnbI5TX/Z0gjEQEn8e+vVEZL/tcztiZbTitFiv21WcNZxqog76jPJ2nKG+S7+dbFeQtncnom8THhh+MkOcZyHfKXwXHLg3HAnK4avTx16hvI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070151; c=relaxed/simple; bh=3pchN+pfse7OhFbYOp4jOrcitCkUW+5Lr2GZQhfxYuM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RYBcXwCQNr/vgOaj2X8bpgnM6IcX+FdpBvv6ycG0F1O7crhg94nZt1BatOfcKoJAxnFDYNG7Yu2WqoOCG0fhdaEKjPIla/exSwHA2HNz8pfMCk0gaj4n67gcp3Gszrfb5j3colPdcS4E39TrFN4CTyNOTXa2QRnRYJjVUz3AULQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=YqSACBBb; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="YqSACBBb" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GDqdmn017704; Thu, 16 Jan 2025 23:28:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= i868WUIYLjxpdksSfKv0qa/3/lqtD6DrNqSKKBxBDys=; b=YqSACBBbk9NfYLMw yL12Yz1osz5SOveKFEYgKQ+0y3vJohAKZQDCs1ABmocOL9jBHOUR+e3o5j5M5jUO 4Q8Mr8SvEs0XVK1NVY0biN88sYK+xb0dtjihMAIg0qtx3yglI7VCKRlWcudS7hh3 LbFJxvZ2r2N3Mkp53ABJO9K2YcTgJKLezsgZ902fNWo5RXtXU4HdP98+iOI4YFqI bN5wx7+9wwCr2VtieWGY9Ysu4q/UKcBCenrVNh483xjRaCGFGuTXAec0K+sYyHre rb9D1CXovKVWXbzT8om45WXe2trA7lOvO0/S8KgPGpoVppK2GDW7Zi7+wAaxYi2M CaCKoQ== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473cqh8kj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:50 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSnSr022833 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:49 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:49 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 30/31] ALSA: usb-audio: qcom: Add USB offload route kcontrol Date: Thu, 16 Jan 2025 15:28:23 -0800 Message-ID: <20250116232824.3748438-31-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: MosqNDHbGJ2QJo-vl6eoSt54plt-gnZR X-Proofpoint-GUID: MosqNDHbGJ2QJo-vl6eoSt54plt-gnZR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 phishscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 adultscore=0 mlxscore=0 malwarescore=0 clxscore=1015 priorityscore=1501 impostorscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 In order to allow userspace/applications know about USB offloading status, expose a sound kcontrol that fetches information about which sound card and PCM index the USB device is mapped to for supporting offloading. In the USB audio offloading framework, the ASoC BE DAI link is the entity responsible for registering to the SOC USB layer. It is expected for the USB SND offloading driver to add the kcontrol to the sound card associated with the USB audio device. An example output would look like: tinymix -D 1 get 'USB Offload Playback Route PCM#0' -1, -1 (range -1->255) This example signifies that there is no mapped ASoC path available for the USB SND device. tinymix -D 1 get 'USB Offload Playback Route PCM#0' 0, 0 (range -1->255) This example signifies that the offload path is available over ASoC sound card index#0 and PCM device#0. The USB offload kcontrol will be added in addition to the existing kcontrols identified by the USB SND mixer. The kcontrols used to modify the USB audio device specific parameters are still valid and expected to be used. These parameters are not mirrored to the ASoC subsystem. Signed-off-by: Wesley Cheng --- sound/usb/Kconfig | 10 ++ sound/usb/qcom/Makefile | 4 + sound/usb/qcom/mixer_usb_offload.c | 158 +++++++++++++++++++++++++++++ sound/usb/qcom/mixer_usb_offload.h | 17 ++++ sound/usb/qcom/qc_audio_offload.c | 2 + 5 files changed, 191 insertions(+) create mode 100644 sound/usb/qcom/mixer_usb_offload.c create mode 100644 sound/usb/qcom/mixer_usb_offload.h diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 6daa551738da..7d8833945711 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -176,9 +176,19 @@ config SND_BCD2000 To compile this driver as a module, choose M here: the module will be called snd-bcd2000. +config SND_USB_QC_OFFLOAD_MIXER + tristate "Qualcomm USB Audio Offload mixer control" + help + Say Y to enable the Qualcomm USB audio offloading mixer controls. + This exposes an USB offload capable kcontrol to signal to + applications about which platform sound card can support USB + audio offload. The returning values specify the mapped ASoC card + and PCM device the USB audio device is associated to. + config SND_USB_AUDIO_QMI tristate "Qualcomm Audio Offload driver" depends on QCOM_QMI_HELPERS && SND_USB_AUDIO && USB_XHCI_SIDEBAND && SND_SOC_USB + select SND_USB_OFFLOAD_MIXER help Say Y here to enable the Qualcomm USB audio offloading feature. diff --git a/sound/usb/qcom/Makefile b/sound/usb/qcom/Makefile index 1eb51160e2e5..1efe1b90be7a 100644 --- a/sound/usb/qcom/Makefile +++ b/sound/usb/qcom/Makefile @@ -1,2 +1,6 @@ snd-usb-audio-qmi-y := usb_audio_qmi_v01.o qc_audio_offload.o obj-$(CONFIG_SND_USB_AUDIO_QMI) += snd-usb-audio-qmi.o + +ifneq ($(CONFIG_SND_USB_QC_OFFLOAD_MIXER),) +snd-usb-audio-qmi-y += mixer_usb_offload.o +endif diff --git a/sound/usb/qcom/mixer_usb_offload.c b/sound/usb/qcom/mixer_usb_offload.c new file mode 100644 index 000000000000..2696eb145ef5 --- /dev/null +++ b/sound/usb/qcom/mixer_usb_offload.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include + +#include +#include +#include + +#include "../usbaudio.h" +#include "../card.h" +#include "../helper.h" +#include "../mixer.h" + +#include "mixer_usb_offload.h" + +#define PCM_IDX(n) ((n) & 0xffff) +#define CARD_IDX(n) ((n) >> 16) + +static int +snd_usb_offload_card_route_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct device *sysdev = snd_kcontrol_chip(kcontrol); + int ret; + + ret = snd_soc_usb_update_offload_route(sysdev, + CARD_IDX(kcontrol->private_value), + PCM_IDX(kcontrol->private_value), + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_USB_KCTL_CARD_ROUTE, + ucontrol->value.integer.value); + if (ret < 0) { + ucontrol->value.integer.value[0] = -1; + ucontrol->value.integer.value[1] = -1; + } + + return 0; +} + +static int snd_usb_offload_card_route_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = -1; + uinfo->value.integer.max = SNDRV_CARDS; + + return 0; +} + +static struct snd_kcontrol_new snd_usb_offload_mapped_card_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .info = snd_usb_offload_card_route_info, + .get = snd_usb_offload_card_route_get, +}; + +static int +snd_usb_offload_pcm_route_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct device *sysdev = snd_kcontrol_chip(kcontrol); + int ret; + + ret = snd_soc_usb_update_offload_route(sysdev, + CARD_IDX(kcontrol->private_value), + PCM_IDX(kcontrol->private_value), + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_USB_KCTL_PCM_ROUTE, + ucontrol->value.integer.value); + if (ret < 0) { + ucontrol->value.integer.value[0] = -1; + ucontrol->value.integer.value[1] = -1; + } + + return 0; +} + +static int snd_usb_offload_pcm_route_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = -1; + /* Arbitrary max value, as there is no 'limit' on number of PCM devices */ + uinfo->value.integer.max = 0xff; + + return 0; +} + +static struct snd_kcontrol_new snd_usb_offload_mapped_pcm_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .info = snd_usb_offload_pcm_route_info, + .get = snd_usb_offload_pcm_route_get, +}; + +/** + * snd_usb_offload_create_ctl() - Add USB offload bounded mixer + * @chip - USB SND chip device + * + * Creates a sound control for a USB audio device, so that applications can + * query for if there is an available USB audio offload path, and which + * card is managing it. + */ +int snd_usb_offload_create_ctl(struct snd_usb_audio *chip) +{ + struct usb_device *udev = chip->dev; + struct snd_kcontrol_new *chip_kctl; + struct snd_usb_substream *subs; + struct snd_usb_stream *as; + char ctl_name[34]; + int ret; + + list_for_each_entry(as, &chip->pcm_list, list) { + subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK]; + if (!subs->ep_num || as->pcm_index > 0xff) + continue; + + chip_kctl = &snd_usb_offload_mapped_card_ctl; + chip_kctl->count = 1; + /* + * Store the associated USB SND card number and PCM index for + * the kctl. + */ + chip_kctl->private_value = as->pcm_index | + chip->card->number << 16; + sprintf(ctl_name, "USB Offload Playback Card Route PCM#%d", + as->pcm_index); + chip_kctl->name = ctl_name; + ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, + udev->bus->sysdev)); + if (ret < 0) + break; + + chip_kctl = &snd_usb_offload_mapped_pcm_ctl; + chip_kctl->count = 1; + /* + * Store the associated USB SND card number and PCM index for + * the kctl. + */ + chip_kctl->private_value = as->pcm_index | + chip->card->number << 16; + sprintf(ctl_name, "USB Offload Playback PCM Route PCM#%d", + as->pcm_index); + chip_kctl->name = ctl_name; + ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, + udev->bus->sysdev)); + if (ret < 0) + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_usb_offload_create_ctl); diff --git a/sound/usb/qcom/mixer_usb_offload.h b/sound/usb/qcom/mixer_usb_offload.h new file mode 100644 index 000000000000..9ab137105af3 --- /dev/null +++ b/sound/usb/qcom/mixer_usb_offload.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __USB_OFFLOAD_MIXER_H +#define __USB_OFFLOAD_MIXER_H + +#if IS_ENABLED(CONFIG_SND_USB_QC_OFFLOAD_MIXER) +int snd_usb_offload_create_ctl(struct snd_usb_audio *chip); +#else +static inline int snd_usb_offload_create_ctl(struct snd_usb_audio *chip) +{ + return 0; +} +#endif +#endif /* __USB_OFFLOAD_MIXER_H */ diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 29302446e9da..81f75ca34e4d 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -37,6 +37,7 @@ #include "../pcm.h" #include "../power.h" +#include "mixer_usb_offload.h" #include "usb_audio_qmi_v01.h" /* Stream disable request timeout during USB device disconnect */ @@ -1813,6 +1814,7 @@ static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip) sdev->card_idx = chip->card->number; sdev->chip_idx = chip->index; + snd_usb_offload_create_ctl(chip); snd_soc_usb_connect(usb_get_usb_backend(udev), sdev); } From patchwork Thu Jan 16 23:28:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 858137 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3994C23F263; Thu, 16 Jan 2025 23:29:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070144; cv=none; b=oSwRXE68n2JSOWiu+n3uGCrbgSjtUE29Ergu9b2NKIMnU655pbiqKPzws8lWZAJiKFUv5HRk6rhDZt7bz3c58L1EpdL8PkP7IJDyIEofr9g9EjEjgchPjOT7V7jq8VCYQSNnEz5WyShivVhP4rQ0tvsYbGmFsFpyxb3+ZLxq2Ro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737070144; c=relaxed/simple; bh=0OBobLi7ExKS88UXVDqp57BgOzSWIY6pBcXtLyP8eXw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HJDgvA+jNYTNayQ/8bb/5eNgJ2IesekudQVU9YkPBqa2Kn7ysmDnOsJelPVFNRYAqfM5AHgRhtguOZmi/M8Y32fzGctUUnMM+5ib7ZQKEfLSHoQErn+QF7B6iXTkgveEQLhWTWmBdC5Oy7ev1TCeYoS+lFEG5hHOBfvPxLR5eSw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=HkzDf0Cv; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="HkzDf0Cv" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 50GEJkvG005439; Thu, 16 Jan 2025 23:28:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= wcD3BPbhWVoPjRNWO38IFE1Iyo7XgqPy9NMwnNA2krs=; b=HkzDf0Cvm03bC8RM by+U5NIlu7Kq9UHMKKlnzZCZFVwIXByIN806/aZs65Gey6rWp6EZR294kLS2lT4X yGncU84N+C+ihzzPXXtYEgDXw3P0CYISRJfZ1QSK61F2igPJisKmrcVsyuXBOXTq 3qJVg7R7GVTjGarrahX2eBMLAcuCHHJcA7RpsmH7GRYAVhbwnDGVD1dq+QITZeUo yD1go3PGSWTamkRQhurMKlAuD1oqKko6XTKshu7PnFubNc1uhZ+IN4g4aTOXZKyx WA/M2jQxNVdWalr9LEb7aWrSfP75YmBuugZJFt7c2PNgjPlHeQB46qzFeEJiL83d K+mqFw== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4473sfs6n5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:51 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 50GNSoSD019758 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Jan 2025 23:28:50 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 16 Jan 2025 15:28:49 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v33 31/31] ALSA: usb-audio: qcom: Notify USB audio devices on USB offload probing Date: Thu, 16 Jan 2025 15:28:24 -0800 Message-ID: <20250116232824.3748438-32-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250116232824.3748438-1-quic_wcheng@quicinc.com> References: <20250116232824.3748438-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 5mZNvDDBAzGTQa7cLIZfW0dkoxfri0pW X-Proofpoint-ORIG-GUID: 5mZNvDDBAzGTQa7cLIZfW0dkoxfri0pW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-01-16_10,2025-01-16_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 phishscore=0 impostorscore=0 malwarescore=0 priorityscore=1501 suspectscore=0 mlxscore=0 lowpriorityscore=0 clxscore=1015 mlxlogscore=999 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2501160174 If the vendor USB offload class driver is not ready/initialized before USB SND discovers attached devices, utilize snd_usb_rediscover_devices() to find all currently attached devices, so that the ASoC entities are notified on available USB audio devices. Signed-off-by: Wesley Cheng --- sound/usb/qcom/qc_audio_offload.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 81f75ca34e4d..6e1b43cb869e 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1972,6 +1972,8 @@ static int __init qc_usb_audio_offload_init(void) if (ret < 0) goto release_qmi; + snd_usb_rediscover_devices(); + return 0; release_qmi: