From patchwork Thu Jan 26 03:14:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48476 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69795wrn; Wed, 25 Jan 2023 19:17:49 -0800 (PST) X-Google-Smtp-Source: AMrXdXsbrWpeER4eS1rCwhMzXzmNd2xge5Zr2xCCL5d9VSExiv0NcgiFDJ+Vd3LBOZPl6OYTR/+s X-Received: by 2002:a05:6a00:1c9d:b0:577:b52:4ec2 with SMTP id y29-20020a056a001c9d00b005770b524ec2mr31071081pfw.29.1674703069288; Wed, 25 Jan 2023 19:17:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703069; cv=none; d=google.com; s=arc-20160816; b=F/5XfweBs0quttf1xD0acHIa3aQLR/FIvBwEBk7J7cVxzOd6+EHSqty495bgq61d4E UyIYHe3GYUNSHy9RvczonZWV3WYnXfErEVXU7+SGfVk5Y1NQjNbi6P+/pn2X1LB4dq4n iUgJOxHK4Aws7tCuQzshyeZTgK7aFUHAYi8w7CFWxWhrbNXYZntgDLXbS7oWIjxeJeZQ vdcyLybu3nT5FWYoJwO/6c+wkSuYtgNlpi94HbMuNgx9EqsaVcUTdKV7Ox/qWGiYNiSs y63GsuRJFGThd4K46BMkgy1MjNTkmQqkUMhNGKclILO3QuMRodOJ+I0WhCHY1idzYDYs JXsg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=urZbrvlW56jM3NnnnRu12cktuIJHGAwqR4fhPFfPs1k=; b=WD+oKChG75gUrPgIZ+rNYbfKDUlkwpfh1v6LduKAkZB4ddY/osVO5JnQFK+rqNWLTh igUOhi3reyUkwOn1YeX1NpVZmQzGg2c/YYamu6Qy/lLBPK5xjBl4XGhft7QjG3JudOTq UqgWbs8rIWQKKPJHaEYy45JjOnCGK+VCn8iNuAlXwCoXxaEMYu5NdrkxkzxM+/Qxkjf+ 7DvVcGGv7hA4xpqQKBMz0n/zIljDFA/4BzlHFuuqcR4HEbuyv/9rXh/3szwY0OmpQFEl 9AM7QgtBxtFT/Y7kYdoOz3vpVUGHyL7lDkhUwdhXuu/KukaCePO5Hbju2QIw30Y7d5RT 7rqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b="m4/evpnu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 185-20020a6204c2000000b0058e1b16c4d3si7237304pfe.57.2023.01.25.19.17.37; Wed, 25 Jan 2023 19:17:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b="m4/evpnu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236364AbjAZDQl (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46572 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236359AbjAZDQY (ORCPT ); Wed, 25 Jan 2023 22:16:24 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0A1B65EEA; Wed, 25 Jan 2023 19:15:49 -0800 (PST) Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q2tBUR030435; Thu, 26 Jan 2023 03:14:40 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=urZbrvlW56jM3NnnnRu12cktuIJHGAwqR4fhPFfPs1k=; b=m4/evpnuewbvLg5/OxSHVgaYvOb74AxWJqPSFjnw6KRqAvA/ztOj/ZolC03viuo5swXm j6FcsQciXtwMx7LIGea5lbacHQrw8gp6K1nygpzr8bKNZov3oijnyY8eAN+su29m4/Lz A6/OCNLXSZgBpeAHc/qr+xCmZwt7o5/vvRCYHf4H8StiEjY1SwG7axSgFpKH1wa/9LTg vTHFfudfPGDGQG9rkETKymEv57+iPnqq66iiNq+Y2Hb2P3sjNqFd26viFFhbtNgxgaCE Nx23r/tNy0v9u3xgSCyuxFDI6+dFYNFvQMmmvA0q6m+nMGRGa+Xtyvvf7+NLfIY9MqKS iQ== Received: from nasanppmta01.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb2nssqvu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:40 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3Ecpx007834 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:39 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:38 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Mathias Nyman Subject: [RFC PATCH v2 01/22] xhci: fix event ring segment table related masks and variables in header Date: Wed, 25 Jan 2023 19:14:03 -0800 Message-ID: <20230126031424.14582-2-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: Y6vvkQInwFXW-z4RFK3bYsLbLfALUWWl X-Proofpoint-GUID: Y6vvkQInwFXW-z4RFK3bYsLbLfALUWWl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1011 mlxlogscore=999 spamscore=0 malwarescore=0 impostorscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 mlxscore=0 adultscore=0 phishscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053445646839030?= X-GMAIL-MSGID: =?utf-8?q?1756053445646839030?= From: Mathias Nyman xHC controller can supports up to 1024 interrupters. To fit these change the max_interrupters varable from u8 to u16. Add a separate mask for the reserve and preserve bits [5:0] in the erst base register and use it instead of the ERST_PRT_MASK. ERSR_PTR_MASK [3:0] is intended for masking bits in the event ring dequeue pointer register. Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-mem.c | 4 ++-- drivers/usb/host/xhci.h | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 81ca2bc1f0be..679befa97c7a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2529,8 +2529,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) "// Set ERST base address for ir_set 0 = 0x%llx", (unsigned long long)xhci->erst.erst_dma_addr); val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); - val_64 &= ERST_PTR_MASK; - val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); + val_64 &= ERST_BASE_RSVDP; + val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_BASE_RSVDP); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); /* Set the event ring dequeue address */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c9f06c5e4e9d..e1362e0c50e1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -513,6 +513,9 @@ struct xhci_intr_reg { /* Preserve bits 16:31 of erst_size */ #define ERST_SIZE_MASK (0xffff << 16) +/* erst_base bitmasks */ +#define ERST_BASE_RSVDP (0x3f) + /* erst_dequeue bitmasks */ /* Dequeue ERST Segment Index (DESI) - Segment number (or alias) * where the current dequeue pointer lies. This is an optional HW hint. @@ -1773,7 +1776,7 @@ struct xhci_hcd { u8 sbrn; u16 hci_version; u8 max_slots; - u8 max_interrupters; + u16 max_interrupters; u8 max_ports; u8 isoc_threshold; /* imod_interval in ns (I * 250ns) */ From patchwork Thu Jan 26 03:14:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48459 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69113wrn; Wed, 25 Jan 2023 19:15:24 -0800 (PST) X-Google-Smtp-Source: AK7set84h7+W58OkLyiKIQ36IoRDpg3+6gm8mGpnDtzJleEYZ2+zzh4CWhbux/HPQ6oamu5H2fLf X-Received: by 2002:a17:90b:4f43:b0:22b:e304:a85 with SMTP id pj3-20020a17090b4f4300b0022be3040a85mr10307949pjb.28.1674702924208; Wed, 25 Jan 2023 19:15:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702924; cv=none; d=google.com; s=arc-20160816; b=eCVGl2LrBSWrePKt8R3gTN97CzYsghMdKkY8q/i6IR9WHXc4xzziIb7q9wRzXYnqeK tnRNfkU2F1eTuQBofvvM/w4CrkYtaiO3yGfnpqwsJ1rdVJk5f8no/r+kvlr8loL4A+nf kMBmXfeuPC3lnhW/G29ghGd3uD85Xh5H8h3qDay9gyzJiYaDAK0KgOBNiikkuLwj8Iol BYkCO14YnRA1DJUzxtE0B+/lLP+nmfln52+b3C+3GotXeNywKtauHKZY9bCh/j0wR4Ic 8SMd3OTMIKwZxcwdcR6v7F/byDZMCNsyJQjIlIpYQ9Y979OKJxvwkH1qMwksCu7P5imw J7rA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=YnjTkVHuxQtGQzjc/gDmzlIOB8H4c7tQDGmebubRFf4=; b=usXX4QUFXOVDsxJlIx+XGSG+djvID97bX/cLpbSsUaiz3kh2VkkO9Q/xQTP1KENQh8 XVIFKaXaB4RS523PBfijdxvnWyeczXTJwz3f8UEfl9FFicNXWt7sIEdmmz4syPVQ9ppz Sm7HNDLI86Z4YO2yf8jGhuqnJToblFGWWA80y7bBYUg7Emsg7O2Pjn33tvJ9qeM1+ONQ Zj+jKlDevmMYttuKPQzRaoTz0EdAxkgvccayGt0nq2A2l6Gstubp/x5U3wOM3fQrzJtY m5jKZZOxqCH1hTa/OAa+gYQIJjwpQUajgbN0TKhMGLJKvdwZDAwV9Duwam0PZvn5tezW rkgg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=BCUif5Gn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ha3-20020a17090af3c300b0022bb71938casi3822165pjb.50.2023.01.25.19.15.12; Wed, 25 Jan 2023 19:15:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=BCUif5Gn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235756AbjAZDOm (ORCPT + 99 others); Wed, 25 Jan 2023 22:14:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229481AbjAZDOl (ORCPT ); Wed, 25 Jan 2023 22:14:41 -0500 Received: from alexa-out-sd-01.qualcomm.com (alexa-out-sd-01.qualcomm.com [199.106.114.38]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9195264D88; Wed, 25 Jan 2023 19:14:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702880; x=1706238880; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=YnjTkVHuxQtGQzjc/gDmzlIOB8H4c7tQDGmebubRFf4=; b=BCUif5GnrIlLDOEF0k5mQZdFmyWBpfoZHg0MCGG55771k55TyQBwCtfg /8dbuJlxujjBK6l43n6ZLks7WExYKXbeuRCAA5NHyBRv+LjKduNJTAO7N 6ZmdG5zEPZooHmADbVFN1b1iTt6WmN0wxlgVS5QO28yvk+1XEzMgQqs2B 8=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-01.qualcomm.com with ESMTP; 25 Jan 2023 19:14:39 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:39 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:38 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Mathias Nyman Subject: [RFC PATCH v2 02/22] xhci: remove xhci_test_trb_in_td_math early development check Date: Wed, 25 Jan 2023 19:14:04 -0800 Message-ID: <20230126031424.14582-3-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053293301989769?= X-GMAIL-MSGID: =?utf-8?q?1756053293301989769?= From: Mathias Nyman Time to remove this test trb in td math check that was added in early stage of xhci driver deveopment. It verified that the size, alignment and boundaries of the event and command rings the driver itself allocated are correct. Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-mem.c | 160 ------------------------------------ 1 file changed, 160 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 679befa97c7a..bf9bb29f924b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1929,164 +1929,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->usb3_rhub.bus_state.bus_suspended = 0; } -static int xhci_test_trb_in_td(struct xhci_hcd *xhci, - struct xhci_segment *input_seg, - union xhci_trb *start_trb, - union xhci_trb *end_trb, - dma_addr_t input_dma, - struct xhci_segment *result_seg, - char *test_name, int test_number) -{ - unsigned long long start_dma; - unsigned long long end_dma; - struct xhci_segment *seg; - - start_dma = xhci_trb_virt_to_dma(input_seg, start_trb); - end_dma = xhci_trb_virt_to_dma(input_seg, end_trb); - - seg = trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma, false); - if (seg != result_seg) { - xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n", - test_name, test_number); - xhci_warn(xhci, "Tested TRB math w/ seg %p and " - "input DMA 0x%llx\n", - input_seg, - (unsigned long long) input_dma); - xhci_warn(xhci, "starting TRB %p (0x%llx DMA), " - "ending TRB %p (0x%llx DMA)\n", - start_trb, start_dma, - end_trb, end_dma); - xhci_warn(xhci, "Expected seg %p, got seg %p\n", - result_seg, seg); - trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma, - true); - return -1; - } - return 0; -} - -/* TRB math checks for xhci_trb_in_td(), using the command and event rings. */ -static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci) -{ - struct { - dma_addr_t input_dma; - struct xhci_segment *result_seg; - } simple_test_vector [] = { - /* A zeroed DMA field should fail */ - { 0, NULL }, - /* One TRB before the ring start should fail */ - { xhci->event_ring->first_seg->dma - 16, NULL }, - /* One byte before the ring start should fail */ - { xhci->event_ring->first_seg->dma - 1, NULL }, - /* Starting TRB should succeed */ - { xhci->event_ring->first_seg->dma, xhci->event_ring->first_seg }, - /* Ending TRB should succeed */ - { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 1)*16, - xhci->event_ring->first_seg }, - /* One byte after the ring end should fail */ - { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 1)*16 + 1, NULL }, - /* One TRB after the ring end should fail */ - { xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT)*16, NULL }, - /* An address of all ones should fail */ - { (dma_addr_t) (~0), NULL }, - }; - struct { - struct xhci_segment *input_seg; - union xhci_trb *start_trb; - union xhci_trb *end_trb; - dma_addr_t input_dma; - struct xhci_segment *result_seg; - } complex_test_vector [] = { - /* Test feeding a valid DMA address from a different ring */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = xhci->event_ring->first_seg->trbs, - .end_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], - .input_dma = xhci->cmd_ring->first_seg->dma, - .result_seg = NULL, - }, - /* Test feeding a valid end TRB from a different ring */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = xhci->event_ring->first_seg->trbs, - .end_trb = &xhci->cmd_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], - .input_dma = xhci->cmd_ring->first_seg->dma, - .result_seg = NULL, - }, - /* Test feeding a valid start and end TRB from a different ring */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = xhci->cmd_ring->first_seg->trbs, - .end_trb = &xhci->cmd_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], - .input_dma = xhci->cmd_ring->first_seg->dma, - .result_seg = NULL, - }, - /* TRB in this ring, but after this TD */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = &xhci->event_ring->first_seg->trbs[0], - .end_trb = &xhci->event_ring->first_seg->trbs[3], - .input_dma = xhci->event_ring->first_seg->dma + 4*16, - .result_seg = NULL, - }, - /* TRB in this ring, but before this TD */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = &xhci->event_ring->first_seg->trbs[3], - .end_trb = &xhci->event_ring->first_seg->trbs[6], - .input_dma = xhci->event_ring->first_seg->dma + 2*16, - .result_seg = NULL, - }, - /* TRB in this ring, but after this wrapped TD */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], - .end_trb = &xhci->event_ring->first_seg->trbs[1], - .input_dma = xhci->event_ring->first_seg->dma + 2*16, - .result_seg = NULL, - }, - /* TRB in this ring, but before this wrapped TD */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], - .end_trb = &xhci->event_ring->first_seg->trbs[1], - .input_dma = xhci->event_ring->first_seg->dma + (TRBS_PER_SEGMENT - 4)*16, - .result_seg = NULL, - }, - /* TRB not in this ring, and we have a wrapped TD */ - { .input_seg = xhci->event_ring->first_seg, - .start_trb = &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 3], - .end_trb = &xhci->event_ring->first_seg->trbs[1], - .input_dma = xhci->cmd_ring->first_seg->dma + 2*16, - .result_seg = NULL, - }, - }; - - unsigned int num_tests; - int i, ret; - - num_tests = ARRAY_SIZE(simple_test_vector); - for (i = 0; i < num_tests; i++) { - ret = xhci_test_trb_in_td(xhci, - xhci->event_ring->first_seg, - xhci->event_ring->first_seg->trbs, - &xhci->event_ring->first_seg->trbs[TRBS_PER_SEGMENT - 1], - simple_test_vector[i].input_dma, - simple_test_vector[i].result_seg, - "Simple", i); - if (ret < 0) - return ret; - } - - num_tests = ARRAY_SIZE(complex_test_vector); - for (i = 0; i < num_tests; i++) { - ret = xhci_test_trb_in_td(xhci, - complex_test_vector[i].input_seg, - complex_test_vector[i].start_trb, - complex_test_vector[i].end_trb, - complex_test_vector[i].input_dma, - complex_test_vector[i].result_seg, - "Complex", i); - if (ret < 0) - return ret; - } - xhci_dbg(xhci, "TRB math tests passed.\n"); - return 0; -} - static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) { u64 temp; @@ -2506,8 +2348,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) 0, flags); if (!xhci->event_ring) goto fail; - if (xhci_check_trb_in_td_math(xhci) < 0) - goto fail; ret = xhci_alloc_erst(xhci, xhci->event_ring, &xhci->erst, flags); if (ret) From patchwork Thu Jan 26 03:14:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48460 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69166wrn; Wed, 25 Jan 2023 19:15:36 -0800 (PST) X-Google-Smtp-Source: AK7set8br+cgIVUatZGFj0xsKmbNFC03RyRuumH0tbe3LmVZcDjTQ8UzjuqvzraeTDBD19S/A+T2 X-Received: by 2002:a17:90b:3906:b0:22c:f9d:81c6 with SMTP id ob6-20020a17090b390600b0022c0f9d81c6mr3615612pjb.20.1674702936544; Wed, 25 Jan 2023 19:15:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702936; cv=none; d=google.com; s=arc-20160816; b=s9uhw+9HBTWVvjtNuEogsdFdl37LKjIquTr0WOe4L9fOrOixeu5cqSOs/ZkJx0VW5m 9ZWiSFv0RZCZr0tmPVYBIxk5b3QtARiwtkCHpkD+rA+BhCy3IXOnSMTmMbZKZTNwzwwk mpt4iaLqFLD77/lCqgzJcfcLD6RC4OsCKDrsmRS+0rhxtfHsKJMNoW8mAoBXOf3UVNky 4BavZ4i6gtFlAx5k26y4ToG5keqNjcqkb4NxeB9oXrqq844DyUov+Mq0x3LlHGnc+w8O L+Njq4rOWewB3IbRKeTQYavQmQbA5owC9LR47m3TdxCWzb/gVgoLa/XVYjjUotRewDLk DiVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=4k5uKPBM4qarkB6xPeHo7pdL8DPp6w26sAa2PI2Q7bk=; b=D7pYgLnwQwMGRxtebQVmbi4NeCbVs2BRC0uGNVHABidsc6fNeg5oQBy7Ls7FbUz6KD uwN1r7BxjP8tRNYE30thQjK0gOOS5zPyj0glJgyZ3Fz3Aw43dEF0oHTDQZPoZK9Bu5XQ my2reiKyc34oYvT2ID73W/7un5gfclKvMpM13Po2s7w8/nFrSlSM1DhExmXKT4vxeqQS TNNxS1Ka0Q8xhTEPVlEGGQi9kYysIr3XK6Olw/4ZaCrbv/udTrnqoiDmK4kOspNei1wt oUO6nPe2s3jQyICOly1kU+0hsDOlRCd8ceGZoqXVRiTJA8cD/zQFX4kB3IIltws7N9ec /h+A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=mVTvXmte; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b9-20020a63a109000000b004c92a2e33c1si6421304pgf.476.2023.01.25.19.15.21; Wed, 25 Jan 2023 19:15:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=mVTvXmte; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236086AbjAZDOu (ORCPT + 99 others); Wed, 25 Jan 2023 22:14:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43984 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235786AbjAZDOo (ORCPT ); Wed, 25 Jan 2023 22:14:44 -0500 Received: from alexa-out-sd-01.qualcomm.com (alexa-out-sd-01.qualcomm.com [199.106.114.38]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A557A64DAB; Wed, 25 Jan 2023 19:14:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702881; x=1706238881; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=4k5uKPBM4qarkB6xPeHo7pdL8DPp6w26sAa2PI2Q7bk=; b=mVTvXmteBtwwcW02iH7/QetItY0n3Pc/7KJvv70yBeiuCI8ImJ5BYdQP JoVJkuFSVnJv5ut2NJ5DX6tuwglKsNy1z7eYIv6gdAD360fIuRZVotZjj OnJrgLGif0DLSx58u/0iIrFn+M9SOKYRk5Q0EeWtP/JmTr5gzEGMlYRbc k=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-01.qualcomm.com with ESMTP; 25 Jan 2023 19:14:40 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:40 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:39 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Mathias Nyman Subject: [RFC PATCH v2 03/22] xhci: Refactor interrupter code for initial multi interrupter support. Date: Wed, 25 Jan 2023 19:14:05 -0800 Message-ID: <20230126031424.14582-4-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053305891112207?= X-GMAIL-MSGID: =?utf-8?q?1756053305891112207?= From: Mathias Nyman xHC supports several interrupters, each with its own mmio register set, event ring and MSI/MSI-X vector. Transfers can be assigned different interrupters when queued. See xhci 4.17 for details. Current driver only supports one interrupter. Create a xhci_interrupter structure containing an event ring, pointer to mmio registers for this interrupter, variables to store registers over s3 suspend, erst, etc. Add functions to create and free an interrupter, and pass an interrupter pointner to functions that deal with events. Secondary interrupters are also useful without having a interrupt vector. One use case is the xHCI Audio offloading where a DSP unit can take care of specific audio endpoints, and all transfer events related to those endpoints can be mapped to its own interrupter event ring, these event at won't cause actual interrupts that wake the CPU. The DSP polls this separate interupter event ring for new events and handles all data on those audio endpoints. Only minor functional changes such as clearing interrupter registers when freeing the interupeter. Still use only one single interrupter, the primary interrupter. Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-debugfs.c | 2 +- drivers/usb/host/xhci-mem.c | 164 +++++++++++++++++++++----------- drivers/usb/host/xhci-ring.c | 68 +++++++------ drivers/usb/host/xhci.c | 54 +++++++---- drivers/usb/host/xhci.h | 76 +-------------- include/linux/usb/xhci-intr.h | 82 ++++++++++++++++ 6 files changed, 263 insertions(+), 183 deletions(-) create mode 100644 include/linux/usb/xhci-intr.h diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index dc832ddf7033..0bc7fe11f749 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -692,7 +692,7 @@ void xhci_debugfs_init(struct xhci_hcd *xhci) "command-ring", xhci->debugfs_root); - xhci_debugfs_create_ring_dir(xhci, &xhci->event_ring, + xhci_debugfs_create_ring_dir(xhci, &xhci->interrupter->event_ring, "event-ring", xhci->debugfs_root); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bf9bb29f924b..2acd41a18190 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1819,17 +1819,39 @@ int xhci_alloc_erst(struct xhci_hcd *xhci, return 0; } -void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) +static void +xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) { - size_t size; struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + size_t erst_size; + u64 tmp64; + u32 tmp; - size = sizeof(struct xhci_erst_entry) * (erst->num_entries); - if (erst->entries) - dma_free_coherent(dev, size, - erst->entries, - erst->erst_dma_addr); - erst->entries = NULL; + if (!ir) + return; + + erst_size = sizeof(struct xhci_erst_entry) * (ir->erst.num_entries); + if (ir->erst.entries) + dma_free_coherent(dev, erst_size, + ir->erst.entries, + ir->erst.erst_dma_addr); + ir->erst.entries = NULL; + + /* clean out interrupter registers */ + tmp = readl(&ir->ir_set->erst_size); + tmp &= ERST_SIZE_MASK; + writel(tmp, &ir->ir_set->erst_size); + + tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); + tmp64 &= (u64) ERST_PTR_MASK; + xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue); + + /* free interrrupter event ring */ + if (ir->event_ring) + xhci_ring_free(xhci, ir->event_ring); + ir->event_ring = NULL; + + kfree(ir); } void xhci_mem_cleanup(struct xhci_hcd *xhci) @@ -1839,12 +1861,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) cancel_delayed_work_sync(&xhci->cmd_timer); - xhci_free_erst(xhci, &xhci->erst); - - if (xhci->event_ring) - xhci_ring_free(xhci, xhci->event_ring); - xhci->event_ring = NULL; - xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed event ring"); + xhci_free_interrupter(xhci, xhci->interrupter); + xhci->interrupter = NULL; + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed primary event ring"); if (xhci->cmd_ring) xhci_ring_free(xhci, xhci->cmd_ring); @@ -1929,18 +1948,18 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->usb3_rhub.bus_state.bus_suspended = 0; } -static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) +static void xhci_set_hc_event_deq(struct xhci_hcd *xhci, struct xhci_interrupter *ir) { u64 temp; dma_addr_t deq; - deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, - xhci->event_ring->dequeue); + deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg, + ir->event_ring->dequeue); if (!deq) xhci_warn(xhci, "WARN something wrong with SW event ring " "dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ - temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); temp &= ERST_PTR_MASK; /* Don't clear the EHB bit (which is RW1C) because * there might be more events to service. @@ -1950,7 +1969,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) "// Write event ring dequeue pointer, " "preserving EHB bit"); xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, - &xhci->ir_set->erst_dequeue); + &ir->ir_set->erst_dequeue); } static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, @@ -2217,6 +2236,68 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) return 0; } +static struct xhci_interrupter * +xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags) +{ + struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + struct xhci_interrupter *ir; + u64 erst_base; + u32 erst_size; + int ret; + + if (intr_num > xhci->max_interrupters) { + xhci_warn(xhci, "Can't allocate interrupter %d, max interrupters %d\n", + intr_num, xhci->max_interrupters); + return NULL; + } + + if (xhci->interrupter) { + xhci_warn(xhci, "Can't allocate already set up interrupter %d\n", intr_num); + return NULL; + } + + ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev)); + if (!ir) + return NULL; + + ir->ir_set = &xhci->run_regs->ir_set[intr_num]; + ir->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT, + 0, flags); + if (!ir->event_ring) { + xhci_warn(xhci, "Failed to allocate interrupter %d event ring\n", intr_num); + goto fail_ir; + } + + ret = xhci_alloc_erst(xhci, ir->event_ring, &ir->erst, flags); + if (ret) { + xhci_warn(xhci, "Failed to allocate interrupter %d erst\n", intr_num); + goto fail_ev; + + } + /* set ERST count with the number of entries in the segment table */ + erst_size = readl(&ir->ir_set->erst_size); + erst_size &= ERST_SIZE_MASK; + erst_size |= ERST_NUM_SEGS; + writel(erst_size, &ir->ir_set->erst_size); + + erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); + erst_base &= ERST_PTR_MASK; + erst_base |= (ir->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); + xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); + + /* Set the event ring dequeue address of this interrupter */ + xhci_set_hc_event_deq(xhci, ir); + + return ir; + +fail_ev: + xhci_ring_free(xhci, ir->event_ring); +fail_ir: + kfree(ir); + + return NULL; +} + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { dma_addr_t dma; @@ -2224,7 +2305,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) unsigned int val, val2; u64 val_64; u32 page_size, temp; - int i, ret; + int i; INIT_LIST_HEAD(&xhci->cmd_list); @@ -2337,46 +2418,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) " from cap regs base addr", val); xhci->dba = (void __iomem *) xhci->cap_regs + val; /* Set ir_set to interrupt register set 0 */ - xhci->ir_set = &xhci->run_regs->ir_set[0]; - - /* - * Event ring setup: Allocate a normal ring, but also setup - * the event ring segment table (ERST). Section 4.9.3. - */ - xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Allocating event ring"); - xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT, - 0, flags); - if (!xhci->event_ring) - goto fail; - - ret = xhci_alloc_erst(xhci, xhci->event_ring, &xhci->erst, flags); - if (ret) - goto fail; - - /* set ERST count with the number of entries in the segment table */ - val = readl(&xhci->ir_set->erst_size); - val &= ERST_SIZE_MASK; - val |= ERST_NUM_SEGS; - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Write ERST size = %i to ir_set 0 (some bits preserved)", - val); - writel(val, &xhci->ir_set->erst_size); + /* allocate and set up primary interrupter with an event ring. */ xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Set ERST entries to point to event ring."); - /* set the segment table base address */ - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "// Set ERST base address for ir_set 0 = 0x%llx", - (unsigned long long)xhci->erst.erst_dma_addr); - val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); - val_64 &= ERST_BASE_RSVDP; - val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_BASE_RSVDP); - xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); - - /* Set the event ring dequeue address */ - xhci_set_hc_event_deq(xhci); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Wrote ERST address to ir_set 0."); + "Allocating primary event ring"); + xhci->interrupter = xhci_alloc_interrupter(xhci, 0, flags); + if (!xhci->interrupter) + goto fail; xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ddc30037f9ce..993c2dc2cd1a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1830,7 +1830,8 @@ static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci) } static void handle_port_status(struct xhci_hcd *xhci, - union xhci_trb *event) + struct xhci_interrupter *ir, + union xhci_trb *event) { struct usb_hcd *hcd; u32 port_id; @@ -1853,7 +1854,7 @@ static void handle_port_status(struct xhci_hcd *xhci, if ((port_id <= 0) || (port_id > max_ports)) { xhci_warn(xhci, "Port change event with invalid port ID %d\n", port_id); - inc_deq(xhci, xhci->event_ring); + inc_deq(xhci, ir->event_ring); return; } @@ -1983,7 +1984,7 @@ static void handle_port_status(struct xhci_hcd *xhci, cleanup: /* Update event ring dequeue pointer before dropping the lock */ - inc_deq(xhci, xhci->event_ring); + inc_deq(xhci, ir->event_ring); /* Don't make the USB core poll the roothub if we got a bad port status * change event. Besides, at that point we can't tell which roothub @@ -2516,7 +2517,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, * At this point, the host controller is probably hosed and should be reset. */ static int handle_tx_event(struct xhci_hcd *xhci, - struct xhci_transfer_event *event) + struct xhci_interrupter *ir, + struct xhci_transfer_event *event) { struct xhci_virt_ep *ep; struct xhci_ring *ep_ring; @@ -2868,7 +2870,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, * processing missed tds. */ if (!handling_skipped_tds) - inc_deq(xhci, xhci->event_ring); + inc_deq(xhci, ir->event_ring); /* * If ep->skip is set, it means there are missed tds on the @@ -2883,8 +2885,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, err_out: xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", (unsigned long long) xhci_trb_virt_to_dma( - xhci->event_ring->deq_seg, - xhci->event_ring->dequeue), + ir->event_ring->deq_seg, + ir->event_ring->dequeue), lower_32_bits(le64_to_cpu(event->buffer)), upper_32_bits(le64_to_cpu(event->buffer)), le32_to_cpu(event->transfer_len), @@ -2898,7 +2900,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, * Returns >0 for "possibly more events to process" (caller should call again), * otherwise 0 if done. In future, <0 returns should indicate error code. */ -static int xhci_handle_event(struct xhci_hcd *xhci) +static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) { union xhci_trb *event; int update_ptrs = 1; @@ -2906,18 +2908,18 @@ static int xhci_handle_event(struct xhci_hcd *xhci) int ret; /* Event ring hasn't been allocated yet. */ - if (!xhci->event_ring || !xhci->event_ring->dequeue) { - xhci_err(xhci, "ERROR event ring not ready\n"); + if (!ir || !ir->event_ring || !ir->event_ring->dequeue) { + xhci_err(xhci, "ERROR interrupter not ready\n"); return -ENOMEM; } - event = xhci->event_ring->dequeue; + event = ir->event_ring->dequeue; /* Does the HC or OS own the TRB? */ if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) != - xhci->event_ring->cycle_state) + ir->event_ring->cycle_state) return 0; - trace_xhci_handle_event(xhci->event_ring, &event->generic); + trace_xhci_handle_event(ir->event_ring, &event->generic); /* * Barrier between reading the TRB_CYCLE (valid) flag above and any @@ -2932,11 +2934,11 @@ static int xhci_handle_event(struct xhci_hcd *xhci) handle_cmd_completion(xhci, &event->event_cmd); break; case TRB_PORT_STATUS: - handle_port_status(xhci, event); + handle_port_status(xhci, ir, event); update_ptrs = 0; break; case TRB_TRANSFER: - ret = handle_tx_event(xhci, &event->trans_event); + ret = handle_tx_event(xhci, ir, &event->trans_event); if (ret >= 0) update_ptrs = 0; break; @@ -2960,7 +2962,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) if (update_ptrs) /* Update SW event ring dequeue pointer */ - inc_deq(xhci, xhci->event_ring); + inc_deq(xhci, ir->event_ring); /* Are there more items on the event ring? Caller will call us again to * check. @@ -2974,16 +2976,17 @@ static int xhci_handle_event(struct xhci_hcd *xhci) * - To avoid "Event Ring Full Error" condition */ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, - union xhci_trb *event_ring_deq) + struct xhci_interrupter *ir, + union xhci_trb *event_ring_deq) { u64 temp_64; dma_addr_t deq; - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ - if (event_ring_deq != xhci->event_ring->dequeue) { - deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, - xhci->event_ring->dequeue); + if (event_ring_deq != ir->event_ring->dequeue) { + deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg, + ir->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n"); /* @@ -3001,7 +3004,7 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, /* Clear the event handler busy flag (RW1C) */ temp_64 |= ERST_EHB; - xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue); } /* @@ -3013,6 +3016,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); union xhci_trb *event_ring_deq; + struct xhci_interrupter *ir; irqreturn_t ret = IRQ_NONE; u64 temp_64; u32 status; @@ -3050,11 +3054,13 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) status |= STS_EINT; writel(status, &xhci->op_regs->status); + /* This is the handler of the primary interrupter */ + ir = xhci->interrupter; if (!hcd->msi_enabled) { u32 irq_pending; - irq_pending = readl(&xhci->ir_set->irq_pending); + irq_pending = readl(&ir->ir_set->irq_pending); irq_pending |= IMAN_IP; - writel(irq_pending, &xhci->ir_set->irq_pending); + writel(irq_pending, &ir->ir_set->irq_pending); } if (xhci->xhc_state & XHCI_STATE_DYING || @@ -3064,22 +3070,22 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, - &xhci->ir_set->erst_dequeue); + &ir->ir_set->erst_dequeue); ret = IRQ_HANDLED; goto out; } - event_ring_deq = xhci->event_ring->dequeue; + event_ring_deq = ir->event_ring->dequeue; /* FIXME this should be a delayed service routine * that clears the EHB. */ - while (xhci_handle_event(xhci) > 0) { + while (xhci_handle_event(xhci, ir) > 0) { if (event_loop++ < TRBS_PER_SEGMENT / 2) continue; - xhci_update_erst_dequeue(xhci, event_ring_deq); - event_ring_deq = xhci->event_ring->dequeue; + xhci_update_erst_dequeue(xhci, ir, event_ring_deq); + event_ring_deq = ir->event_ring->dequeue; /* ring is half-full, force isoc trbs to interrupt more often */ if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) @@ -3088,7 +3094,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) event_loop = 0; } - xhci_update_erst_dequeue(xhci, event_ring_deq); + xhci_update_erst_dequeue(xhci, ir, event_ring_deq); ret = IRQ_HANDLED; out: diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 79d7931c048a..8b19c6ea3d16 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -613,6 +613,7 @@ static int xhci_init(struct usb_hcd *hcd) static int xhci_run_finished(struct xhci_hcd *xhci) { + struct xhci_interrupter *ir = xhci->interrupter; unsigned long flags; u32 temp; @@ -628,8 +629,8 @@ static int xhci_run_finished(struct xhci_hcd *xhci) writel(temp, &xhci->op_regs->command); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable primary interrupter"); - temp = readl(&xhci->ir_set->irq_pending); - writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); + temp = readl(&ir->ir_set->irq_pending); + writel(ER_IRQ_ENABLE(temp), &ir->ir_set->irq_pending); if (xhci_start(xhci)) { xhci_halt(xhci); @@ -665,7 +666,7 @@ int xhci_run(struct usb_hcd *hcd) u64 temp_64; int ret; struct xhci_hcd *xhci = hcd_to_xhci(hcd); - + struct xhci_interrupter *ir = xhci->interrupter; /* Start the xHCI host controller running only after the USB 2.0 roothub * is setup. */ @@ -680,17 +681,17 @@ int xhci_run(struct usb_hcd *hcd) if (ret) return ret; - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); temp_64 &= ~ERST_PTR_MASK; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "ERST deq = 64'h%0lx", (long unsigned int) temp_64); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Set the interrupt modulation register"); - temp = readl(&xhci->ir_set->irq_control); + temp = readl(&ir->ir_set->irq_control); temp &= ~ER_IRQ_INTERVAL_MASK; temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; - writel(temp, &xhci->ir_set->irq_control); + writel(temp, &ir->ir_set->irq_control); if (xhci->quirks & XHCI_NEC_HOST) { struct xhci_command *command; @@ -769,8 +770,8 @@ static void xhci_stop(struct usb_hcd *hcd) "// Disabling event ring interrupts"); temp = readl(&xhci->op_regs->status); writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); - temp = readl(&xhci->ir_set->irq_pending); - writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); + temp = readl(&xhci->interrupter->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory"); xhci_mem_cleanup(xhci); @@ -832,28 +833,36 @@ EXPORT_SYMBOL_GPL(xhci_shutdown); #ifdef CONFIG_PM static void xhci_save_registers(struct xhci_hcd *xhci) { + struct xhci_interrupter *ir = xhci->interrupter; + xhci->s3.command = readl(&xhci->op_regs->command); xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); - xhci->s3.erst_size = readl(&xhci->ir_set->erst_size); - xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); - xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); - xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending); - xhci->s3.irq_control = readl(&xhci->ir_set->irq_control); + + if (!ir) + return; + + ir->s3_erst_size = readl(&ir->ir_set->erst_size); + ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); + ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); + ir->s3_irq_pending = readl(&ir->ir_set->irq_pending); + ir->s3_irq_control = readl(&ir->ir_set->irq_control); } static void xhci_restore_registers(struct xhci_hcd *xhci) { + struct xhci_interrupter *ir = xhci->interrupter; + writel(xhci->s3.command, &xhci->op_regs->command); writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification); xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); writel(xhci->s3.config_reg, &xhci->op_regs->config_reg); - writel(xhci->s3.erst_size, &xhci->ir_set->erst_size); - xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); - xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); - writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending); - writel(xhci->s3.irq_control, &xhci->ir_set->irq_control); + writel(ir->s3_erst_size, &ir->ir_set->erst_size); + xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base); + xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue); + writel(ir->s3_irq_pending, &ir->ir_set->irq_pending); + writel(ir->s3_irq_control, &ir->ir_set->irq_control); } static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) @@ -1218,8 +1227,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "// Disabling event ring interrupts\n"); temp = readl(&xhci->op_regs->status); writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); - temp = readl(&xhci->ir_set->irq_pending); - writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); + temp = readl(&xhci->interrupter->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending); xhci_dbg(xhci, "cleaning up memory\n"); xhci_mem_cleanup(xhci); @@ -5320,6 +5329,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) if (xhci->hci_version > 0x100) xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2); + /* xhci-plat or xhci-pci might have set max_interrupters already */ + if ((!xhci->max_interrupters) || + xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1)) + xhci->max_interrupters = HCS_MAX_INTRS(xhci->hcs_params1); + xhci->quirks |= quirks; get_quirks(dev, xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e1362e0c50e1..af356cc3b50b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -16,6 +16,7 @@ #include #include #include +#include #include /* Code sharing between pci-quirks and xhci hcd */ @@ -1541,18 +1542,6 @@ static inline const char *xhci_trb_type_string(u8 type) #define AVOID_BEI_INTERVAL_MIN 8 #define AVOID_BEI_INTERVAL_MAX 32 -struct xhci_segment { - union xhci_trb *trbs; - /* private to HCD */ - struct xhci_segment *next; - dma_addr_t dma; - /* Max packet sized bounce buffer for td-fragmant alignment */ - dma_addr_t bounce_dma; - void *bounce_buf; - unsigned int bounce_offs; - unsigned int bounce_len; -}; - enum xhci_cancelled_td_status { TD_DIRTY = 0, TD_HALTED, @@ -1585,16 +1574,6 @@ struct xhci_cd { union xhci_trb *cmd_trb; }; -enum xhci_ring_type { - TYPE_CTRL = 0, - TYPE_ISOC, - TYPE_BULK, - TYPE_INTR, - TYPE_STREAM, - TYPE_COMMAND, - TYPE_EVENT, -}; - static inline const char *xhci_ring_type_string(enum xhci_ring_type type) { switch (type) { @@ -1617,47 +1596,6 @@ static inline const char *xhci_ring_type_string(enum xhci_ring_type type) return "UNKNOWN"; } -struct xhci_ring { - struct xhci_segment *first_seg; - struct xhci_segment *last_seg; - union xhci_trb *enqueue; - struct xhci_segment *enq_seg; - union xhci_trb *dequeue; - struct xhci_segment *deq_seg; - struct list_head td_list; - /* - * Write the cycle state into the TRB cycle field to give ownership of - * the TRB to the host controller (if we are the producer), or to check - * if we own the TRB (if we are the consumer). See section 4.9.1. - */ - u32 cycle_state; - unsigned int stream_id; - unsigned int num_segs; - unsigned int num_trbs_free; - unsigned int num_trbs_free_temp; - unsigned int bounce_buf_len; - enum xhci_ring_type type; - bool last_td_was_short; - struct radix_tree_root *trb_address_map; -}; - -struct xhci_erst_entry { - /* 64-bit event ring segment address */ - __le64 seg_addr; - __le32 seg_size; - /* Set to zero */ - __le32 rsvd; -}; - -struct xhci_erst { - struct xhci_erst_entry *entries; - unsigned int num_entries; - /* xhci->event_ring keeps track of segment dma addresses */ - dma_addr_t erst_dma_addr; - /* Num entries the ERST can contain */ - unsigned int erst_size; -}; - struct xhci_scratchpad { u64 *sp_array; dma_addr_t sp_dma; @@ -1687,11 +1625,6 @@ struct s3_save { u32 dev_nt; u64 dcbaa_ptr; u32 config_reg; - u32 irq_pending; - u32 irq_control; - u32 erst_size; - u64 erst_base; - u64 erst_dequeue; }; /* Use for lpm */ @@ -1718,7 +1651,6 @@ struct xhci_bus_state { struct completion u3exit_done[USB_MAXCHILDREN]; }; - /* * It can take up to 20 ms to transition from RExit to U0 on the * Intel Lynx Point LP xHCI host. @@ -1760,8 +1692,6 @@ struct xhci_hcd { struct xhci_op_regs __iomem *op_regs; struct xhci_run_regs __iomem *run_regs; struct xhci_doorbell_array __iomem *dba; - /* Our HCD's current interrupter register set */ - struct xhci_intr_reg __iomem *ir_set; /* Cached register copies of read-only HC data */ __u32 hcs_params1; @@ -1796,6 +1726,7 @@ struct xhci_hcd { struct reset_control *reset; /* data structures */ struct xhci_device_context_array *dcbaa; + struct xhci_interrupter *interrupter; struct xhci_ring *cmd_ring; unsigned int cmd_ring_state; #define CMD_RING_STATE_RUNNING (1 << 0) @@ -1806,8 +1737,7 @@ struct xhci_hcd { struct delayed_work cmd_timer; struct completion cmd_ring_stop_completion; struct xhci_command *current_cmd; - struct xhci_ring *event_ring; - struct xhci_erst erst; + /* Scratchpad */ struct xhci_scratchpad *scratchpad; diff --git a/include/linux/usb/xhci-intr.h b/include/linux/usb/xhci-intr.h new file mode 100644 index 000000000000..9b3fcc9a1842 --- /dev/null +++ b/include/linux/usb/xhci-intr.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_XHCI_INTR_H +#define __LINUX_XHCI_INTR_H + +#include + +struct xhci_erst_entry { + /* 64-bit event ring segment address */ + __le64 seg_addr; + __le32 seg_size; + /* Set to zero */ + __le32 rsvd; +}; + +enum xhci_ring_type { + TYPE_CTRL = 0, + TYPE_ISOC, + TYPE_BULK, + TYPE_INTR, + TYPE_STREAM, + TYPE_COMMAND, + TYPE_EVENT, +}; + +struct xhci_erst { + struct xhci_erst_entry *entries; + unsigned int num_entries; + /* xhci->event_ring keeps track of segment dma addresses */ + dma_addr_t erst_dma_addr; + /* Num entries the ERST can contain */ + unsigned int erst_size; +}; + +struct xhci_segment { + union xhci_trb *trbs; + /* private to HCD */ + struct xhci_segment *next; + dma_addr_t dma; + /* Max packet sized bounce buffer for td-fragmant alignment */ + dma_addr_t bounce_dma; + void *bounce_buf; + unsigned int bounce_offs; + unsigned int bounce_len; +}; + +struct xhci_ring { + struct xhci_segment *first_seg; + struct xhci_segment *last_seg; + union xhci_trb *enqueue; + struct xhci_segment *enq_seg; + union xhci_trb *dequeue; + struct xhci_segment *deq_seg; + struct list_head td_list; + /* + * Write the cycle state into the TRB cycle field to give ownership of + * the TRB to the host controller (if we are the producer), or to check + * if we own the TRB (if we are the consumer). See section 4.9.1. + */ + u32 cycle_state; + unsigned int stream_id; + unsigned int num_segs; + unsigned int num_trbs_free; + unsigned int num_trbs_free_temp; + unsigned int bounce_buf_len; + enum xhci_ring_type type; + bool last_td_was_short; + struct radix_tree_root *trb_address_map; +}; + +struct xhci_interrupter { + struct xhci_ring *event_ring; + struct xhci_erst erst; + struct xhci_intr_reg __iomem *ir_set; + unsigned int intr_num; + /* For interrupter registers save and restore over suspend/resume */ + u32 s3_irq_pending; + u32 s3_irq_control; + u32 s3_erst_size; + u64 s3_erst_base; + u64 s3_erst_dequeue; +}; +#endif From patchwork Thu Jan 26 03:14:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48462 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69242wrn; Wed, 25 Jan 2023 19:15:57 -0800 (PST) X-Google-Smtp-Source: AK7set8hQdVVTQB58/mXBuYLQB+1ZcZcdbs9AhU6OaOxJ5XcjUPAsJGmTCpKkzPxLvgxxjj7k++C X-Received: by 2002:a17:90b:1642:b0:229:f580:e68a with SMTP id il2-20020a17090b164200b00229f580e68amr621139pjb.17.1674702957639; Wed, 25 Jan 2023 19:15:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702957; cv=none; d=google.com; s=arc-20160816; b=fosc8SBdcJT1zNOjmU7o5XQ6y0c1cz7RWdOPQiGrOVgsaVjgNEdO09AopfPW/Qjf/+ EEcMg0inDV/17mIv3uHPuHwSxU32coUMebUcBb4nbIrRYDbjnmBp4pt/qYriNEtX3eZw JQsAyFRDQWe7AF7JWKYUQ0AyhyC8oG1sdEadx3yJhnPPS37THDx5b2ZLUnB5AZm58yJf 5n5ZSeVBqD3zdMt3ZVOnj/jEDV6WS2dswsI0/KJkqNjd8FodoFXNfiaZMyz3cXM2rHIb d7TtmSlBoaQKioIjqsi+FlXRCMal8ziKqDFXF+G0j6nkiTvRsiJMMGU/TTBcqe7cjVc1 1BBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=hfiPgKvzjZwkMX/Yp7b1WkmuzfwbKyPbUhif802Ho3w=; b=koImP68WFOx4zLbQzGbqLvC54WyjvjvBvHK+xKQhMkxiMP9XZSK1uo/Sg5TarO3SLR UytVIkOo3AzG55M5ztqLaXs7f9xnGKnXd0PoRtbOaOnb4b44DwFDaBO3tanwNLTDPU9t E7d8ovGuNsWOdKOEIbli4G6S9xQacCrQbwvFVjEJk1wRLBxxdcCZjXWCaWOJ9I2Az06w K+khZxypSOWiOX98JzKm7rejAXiZahCmSGu9fgNRAitsz/1pmMCEuBtzZMSqIevFVQPd PKUuksI04cjCTs16ejhRYODAifB0l7ZwBRoFX2xm1FfAsqHpBV/HxU0qsvvz3ZC/FdhI vovw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=UfuczVMi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id l3-20020a17090a408300b0022955e2f7ccsi332666pjg.21.2023.01.25.19.15.45; Wed, 25 Jan 2023 19:15:57 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=UfuczVMi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236109AbjAZDOz (ORCPT + 99 others); Wed, 25 Jan 2023 22:14:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235811AbjAZDOp (ORCPT ); Wed, 25 Jan 2023 22:14:45 -0500 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9416C65ED5; Wed, 25 Jan 2023 19:14:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702883; x=1706238883; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=hfiPgKvzjZwkMX/Yp7b1WkmuzfwbKyPbUhif802Ho3w=; b=UfuczVMiYue1/MCASUMsD6eFDL8eGSkt0MY07DdfqdIs1Ba4zYnfRRK0 57QA4gxanr8T1rtS+JJ8jE7dvFj6K1ppL5qLYyg6sqSySAkjKRnebxeLO iWDyrLkqulA4sykABjKbE29FvS5RjeW9NSIQAsWXuqAsGSpwzHJX2Imnj 0=; Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-02.qualcomm.com with ESMTP; 25 Jan 2023 19:14:41 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg-SD-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:41 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:40 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Mathias Nyman Subject: [RFC PATCH v2 04/22] xhci: Add support to allocate several interrupters Date: Wed, 25 Jan 2023 19:14:06 -0800 Message-ID: <20230126031424.14582-5-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053328558540886?= X-GMAIL-MSGID: =?utf-8?q?1756053328558540886?= From: Mathias Nyman Introduce xHCI APIs to allow for clients to allocate and free interrupters. This allocates an array of interrupters, which is based on the max_interrupters parameter. The primary interrupter is set as the first entry in the array, and secondary interrupters following after. Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-debugfs.c | 2 +- drivers/usb/host/xhci-mem.c | 97 +++++++++++++++++++++++++++++++-- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/host/xhci.c | 55 ++++++++++++------- drivers/usb/host/xhci.h | 2 +- include/linux/usb/xhci-intr.h | 4 ++ 6 files changed, 134 insertions(+), 28 deletions(-) diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 0bc7fe11f749..06a42b68446f 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -692,7 +692,7 @@ void xhci_debugfs_init(struct xhci_hcd *xhci) "command-ring", xhci->debugfs_root); - xhci_debugfs_create_ring_dir(xhci, &xhci->interrupter->event_ring, + xhci_debugfs_create_ring_dir(xhci, &xhci->interrupters[0]->event_ring, "event-ring", xhci->debugfs_root); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2acd41a18190..45ac77a5d8e4 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1854,6 +1854,30 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) kfree(ir); } +/* + * Free a secondary interrupter slot. This will allow for other users to request for + * the secondary interrupter in the future. + */ +void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + unsigned int intr_num; + unsigned long flags; + + if (!ir || !ir->intr_num || ir->intr_num > xhci->max_interrupters) { + xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n"); + return; + } + + /* fixme, shuld we check xhci->interrupter[intr_num] == ir */ + intr_num = ir->intr_num; + xhci_free_interrupter(xhci, ir); + spin_lock_irqsave(&xhci->lock, flags); + xhci->interrupters[intr_num] = NULL; + spin_unlock_irqrestore(&xhci->lock, flags); +} +EXPORT_SYMBOL_GPL(xhci_remove_secondary_interrupter); + void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct device *dev = xhci_to_hcd(xhci)->self.sysdev; @@ -1861,8 +1885,15 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) cancel_delayed_work_sync(&xhci->cmd_timer); - xhci_free_interrupter(xhci, xhci->interrupter); - xhci->interrupter = NULL; + for (i = 1; i < xhci->max_interrupters; i++) { + if (xhci->interrupters[i]) + xhci_remove_secondary_interrupter(xhci_to_hcd(xhci), + xhci->interrupters[i]); + } + + /* free the primary interrupter, interrupter number 0 */ + xhci_free_interrupter(xhci, xhci->interrupters[0]); + xhci->interrupters[0] = NULL; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed primary event ring"); if (xhci->cmd_ring) @@ -1933,6 +1964,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) for (i = 0; i < xhci->num_port_caps; i++) kfree(xhci->port_caps[i].psi); kfree(xhci->port_caps); + kfree(xhci->interrupters); xhci->num_port_caps = 0; xhci->usb2_rhub.ports = NULL; @@ -1941,6 +1973,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->rh_bw = NULL; xhci->ext_caps = NULL; xhci->port_caps = NULL; + xhci->interrupters = NULL; xhci->page_size = 0; xhci->page_shift = 0; @@ -2251,7 +2284,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags return NULL; } - if (xhci->interrupter) { + if (xhci->interrupters[intr_num]) { xhci_warn(xhci, "Can't allocate already set up interrupter %d\n", intr_num); return NULL; } @@ -2298,6 +2331,56 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags return NULL; } +/* + * Allocate a XHCI secondary interrupter slot. If the user requests a specific intr + * number, then check if the slot is available. Otherwise, fetch the first available + * entry within the interrupter array. + */ +struct xhci_interrupter * +xhci_create_secondary_interrupter(struct usb_hcd *hcd, int intr_num) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_interrupter *ir; + unsigned int i; + unsigned int idx = 0; + unsigned long flags; + + if (!xhci->interrupters || intr_num > xhci->max_interrupters) + return NULL; + + spin_lock_irqsave(&xhci->lock, flags); + /* find available secondary interrupter, interrupter 0 is reserved for primary */ + if (intr_num > 0) { + idx = intr_num; + } else { + for (i = 1; i < xhci->max_interrupters; i++) { + if (xhci->interrupters[i] == NULL) { + idx = i; + break; + } + } + } + + if (idx > 0) { + ir = xhci_alloc_interrupter(xhci, idx, GFP_KERNEL); + if (!ir) { + spin_unlock_irqrestore(&xhci->lock, flags); + return NULL; + } + ir->intr_num = idx; + xhci->interrupters[idx] = ir; + spin_unlock_irqrestore(&xhci->lock, flags); + + return ir; + } + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_warn(xhci, "Can't add new secondary interrupter, max interrupters %d\n", + xhci->max_interrupters); + + return NULL; +} +EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter); + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { dma_addr_t dma; @@ -2422,8 +2505,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) /* allocate and set up primary interrupter with an event ring. */ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Allocating primary event ring"); - xhci->interrupter = xhci_alloc_interrupter(xhci, 0, flags); - if (!xhci->interrupter) + + xhci->interrupters = kcalloc_node(xhci->max_interrupters, sizeof(*xhci->interrupters), + flags, dev_to_node(dev)); + + xhci->interrupters[0] = xhci_alloc_interrupter(xhci, 0, flags); + if (!xhci->interrupters[0]) goto fail; xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 993c2dc2cd1a..2c20ccdc95bc 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3055,7 +3055,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) writel(status, &xhci->op_regs->status); /* This is the handler of the primary interrupter */ - ir = xhci->interrupter; + ir = xhci->interrupters[0]; if (!hcd->msi_enabled) { u32 irq_pending; irq_pending = readl(&ir->ir_set->irq_pending); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8b19c6ea3d16..003c6cc2fb55 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -613,7 +613,7 @@ static int xhci_init(struct usb_hcd *hcd) static int xhci_run_finished(struct xhci_hcd *xhci) { - struct xhci_interrupter *ir = xhci->interrupter; + struct xhci_interrupter *ir = xhci->interrupters[0]; unsigned long flags; u32 temp; @@ -666,7 +666,7 @@ int xhci_run(struct usb_hcd *hcd) u64 temp_64; int ret; struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct xhci_interrupter *ir = xhci->interrupter; + struct xhci_interrupter *ir = xhci->interrupters[0]; /* Start the xHCI host controller running only after the USB 2.0 roothub * is setup. */ @@ -770,8 +770,8 @@ static void xhci_stop(struct usb_hcd *hcd) "// Disabling event ring interrupts"); temp = readl(&xhci->op_regs->status); writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); - temp = readl(&xhci->interrupter->ir_set->irq_pending); - writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending); + temp = readl(&xhci->interrupters[0]->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->interrupters[0]->ir_set->irq_pending); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory"); xhci_mem_cleanup(xhci); @@ -833,36 +833,51 @@ EXPORT_SYMBOL_GPL(xhci_shutdown); #ifdef CONFIG_PM static void xhci_save_registers(struct xhci_hcd *xhci) { - struct xhci_interrupter *ir = xhci->interrupter; + struct xhci_interrupter *ir; + unsigned int i; xhci->s3.command = readl(&xhci->op_regs->command); xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); - if (!ir) - return; + /* save both primary and all secondary interrupters */ + /* fixme, shold we lock to prevent race with remove secondary interrupter? */ + for (i = 0; i < xhci->max_interrupters; i++) { + ir = xhci->interrupters[i]; + if (!ir) + continue; - ir->s3_erst_size = readl(&ir->ir_set->erst_size); - ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); - ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); - ir->s3_irq_pending = readl(&ir->ir_set->irq_pending); - ir->s3_irq_control = readl(&ir->ir_set->irq_control); + ir->s3_erst_size = readl(&ir->ir_set->erst_size); + ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); + ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); + ir->s3_irq_pending = readl(&ir->ir_set->irq_pending); + ir->s3_irq_control = readl(&ir->ir_set->irq_control); + } } static void xhci_restore_registers(struct xhci_hcd *xhci) { - struct xhci_interrupter *ir = xhci->interrupter; + struct xhci_interrupter *ir; + unsigned int i; writel(xhci->s3.command, &xhci->op_regs->command); writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification); xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); writel(xhci->s3.config_reg, &xhci->op_regs->config_reg); - writel(ir->s3_erst_size, &ir->ir_set->erst_size); - xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base); - xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue); - writel(ir->s3_irq_pending, &ir->ir_set->irq_pending); - writel(ir->s3_irq_control, &ir->ir_set->irq_control); + + /* FIXME should we lock to protect against freeing of interrupters */ + for (i = 0; i < xhci->max_interrupters; i++) { + ir = xhci->interrupters[i]; + if (!ir) + continue; + + writel(ir->s3_erst_size, &ir->ir_set->erst_size); + xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base); + xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue); + writel(ir->s3_irq_pending, &ir->ir_set->irq_pending); + writel(ir->s3_irq_control, &ir->ir_set->irq_control); + } } static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) @@ -1227,8 +1242,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "// Disabling event ring interrupts\n"); temp = readl(&xhci->op_regs->status); writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); - temp = readl(&xhci->interrupter->ir_set->irq_pending); - writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending); + temp = readl(&xhci->interrupters[0]->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->interrupters[0]->ir_set->irq_pending); xhci_dbg(xhci, "cleaning up memory\n"); xhci_mem_cleanup(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index af356cc3b50b..f45cbfb79cea 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1726,7 +1726,7 @@ struct xhci_hcd { struct reset_control *reset; /* data structures */ struct xhci_device_context_array *dcbaa; - struct xhci_interrupter *interrupter; + struct xhci_interrupter **interrupters; struct xhci_ring *cmd_ring; unsigned int cmd_ring_state; #define CMD_RING_STATE_RUNNING (1 << 0) diff --git a/include/linux/usb/xhci-intr.h b/include/linux/usb/xhci-intr.h index 9b3fcc9a1842..738b0f0481a6 100644 --- a/include/linux/usb/xhci-intr.h +++ b/include/linux/usb/xhci-intr.h @@ -79,4 +79,8 @@ struct xhci_interrupter { u64 s3_erst_base; u64 s3_erst_dequeue; }; + +struct xhci_interrupter * +xhci_create_secondary_interrupter(struct usb_hcd *hcd, int intr_num); +void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir); #endif From patchwork Thu Jan 26 03:14:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48461 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69180wrn; Wed, 25 Jan 2023 19:15:40 -0800 (PST) X-Google-Smtp-Source: AMrXdXueSrRk52G0Y3qAvBnHG7t43J4EP+QcoqYTuSkyZ4927b3KT12plneCtjskfALm96pYJSN8 X-Received: by 2002:aa7:c9c7:0:b0:499:cc32:6a52 with SMTP id i7-20020aa7c9c7000000b00499cc326a52mr47440103edt.16.1674702940680; Wed, 25 Jan 2023 19:15:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702940; cv=none; d=google.com; s=arc-20160816; b=fBLhi5t5DGk8b0ZlIOHGnYWaE0CbT7XSgaBoNGlkuX62rZTO1/0gLWQiI99dSVlaat XIAdDwA1frCE1MvmeTBML9ytsmTEaCJuHIE+VFwnA/NhYzrNXQWfmf8ygTRMvhTClL8i xzCHezAB6oa7uwd69YZraa+lJ8Tw0elP8rMpUIJbFV3ZEeDbu86mUbMlnv2oqPQYwRbu uIFNCciS/bQTvbjUbFxMZsz7HhMDsSSOcLWxzeKKN3VSWsVexGqVVEg2VgVFk3NfwvXV jmPGOCWUa0/5GR+4LlLumPlnZ67G0Noh7t4mTFV6JcJvTWKfxEC1MXyclIyWW3bTggIS LevQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=F8qLeDa97kg2MOUQG0PUj/xnkvDv+6xRtHu1IQh2yrk=; b=CgPVil5q0BrMcnRb/1JZWPAlugouuCWA53C5E0SATOz/OjG3YA1Sax4cOEnMcCBDNy 7BeB3h042vd3EZjGW1ZDeEpLneSdkhura+pu/wXn8pTz6RG8zIrjvFQf4AByZUFbM8+c XeuLDxI2NNoftFsjtv7phmMrK7AoYVR873AD3HYCdrJAsAn0ZL5Dgb+nB+ZaNi2vqonF tZ5EOJ85acrzE/Gss308dgLzjebErMDakgRLfTO7pDPHaJRA7R6+ZbbpOrZrX40FfZgl 588KIWHe/XllT/nl2G6kHVgxlP7KYZUGUOL/O6qRuaB+KTRw7kFofqgbFup7hL7sTDxe CWJQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=wgQlATlJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q8-20020a056402248800b0049e1b840be0si495927eda.9.2023.01.25.19.15.15; Wed, 25 Jan 2023 19:15:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=wgQlATlJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235934AbjAZDOs (ORCPT + 99 others); Wed, 25 Jan 2023 22:14:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235773AbjAZDOn (ORCPT ); Wed, 25 Jan 2023 22:14:43 -0500 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 16D7F64D88; Wed, 25 Jan 2023 19:14:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702882; x=1706238882; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=F8qLeDa97kg2MOUQG0PUj/xnkvDv+6xRtHu1IQh2yrk=; b=wgQlATlJEuujq7MbnbfECyFhsRzkzQHCkRBTrYPSPCY46VCT4aN5LXhl KLQiDXha8lUhL+u4vFQZOtLRwYbHg5YDExIJ/OmHfFHAA9H9JNm5sHr3P Y6LCSNlzb44TyYMAN1DkeLzxkwuhNJLWilDzFRNu89I8Ih6Z3WnKOFvix A=; Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-02.qualcomm.com with ESMTP; 25 Jan 2023 19:14:41 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg-SD-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:41 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:40 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 05/22] usb: xhci: Add XHCI APIs to support USB offloading Date: Wed, 25 Jan 2023 19:14:07 -0800 Message-ID: <20230126031424.14582-6-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053310589387981?= X-GMAIL-MSGID: =?utf-8?q?1756053310589387981?= Some use cases, such as USB audio offloading, will allow for a DSP to take over issuing USB transfers to the host controller. In order for the DSP to submit transfers for a particular endpoint, and to handle its events, the client driver will need to query for some parameters allocated by XHCI. - XHCI secondary interrupter event ring address - XHCI transfer ring address (for a particular EP) - Stop endpoint command API Once the resources are handed off to the DSP, the offload begins, and the main processor can enter idle. When stopped, since there are no URBs submitted from the main processor, the client will just issue a stop endpoint command to halt any pending transfers. Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci.c | 130 ++++++++++++++++++++++++++++++++++ include/linux/usb/xhci-intr.h | 8 +++ 2 files changed, 138 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 003c6cc2fb55..36d81ecdb890 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1580,6 +1580,136 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, return 1; } +int xhci_stop_endpoint(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + unsigned int ep_index; + struct xhci_virt_device *virt_dev; + struct xhci_command *cmd; + unsigned long flags; + int ret = 0; + + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); + if (ret <= 0) + return ret; + + cmd = xhci_alloc_command(xhci, true, GFP_NOIO); + if (!cmd) + return -ENOMEM; + + spin_lock_irqsave(&xhci->lock, flags); + virt_dev = xhci->devs[udev->slot_id]; + if (!virt_dev) { + ret = -ENODEV; + goto err; + } + + ep_index = xhci_get_endpoint_index(&ep->desc); + if (virt_dev->eps[ep_index].ring && + virt_dev->eps[ep_index].ring->dequeue) { + ret = xhci_queue_stop_endpoint(xhci, cmd, udev->slot_id, + ep_index, 0); + if (ret) + goto err; + + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); + + /* Wait for stop endpoint command to finish */ + wait_for_completion(cmd->completion); + + if (cmd->status == COMP_COMMAND_ABORTED || + cmd->status == COMP_STOPPED) { + xhci_warn(xhci, + "stop endpoint command timeout for ep%d%s\n", + usb_endpoint_num(&ep->desc), + usb_endpoint_dir_in(&ep->desc) ? "in" : "out"); + ret = -ETIME; + } + goto free_cmd; + } + +err: + spin_unlock_irqrestore(&xhci->lock, flags); +free_cmd: + xhci_free_command(xhci, cmd); + + return ret; +} +EXPORT_SYMBOL_GPL(xhci_stop_endpoint); + +/* Retrieve the transfer ring base address for a specific endpoint. */ +phys_addr_t xhci_get_xfer_resource(struct usb_device *udev, + struct usb_host_endpoint *ep, dma_addr_t *dma) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct device *dev = hcd->self.sysdev; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct sg_table sgt; + phys_addr_t pa; + int ret; + unsigned int ep_index; + struct xhci_virt_device *virt_dev; + unsigned long flags; + + if (!HCD_RH_RUNNING(hcd)) + return 0; + + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); + if (ret <= 0) { + xhci_err(xhci, "%s: invalid args\n", __func__); + return 0; + } + + spin_lock_irqsave(&xhci->lock, flags); + + virt_dev = xhci->devs[udev->slot_id]; + ep_index = xhci_get_endpoint_index(&ep->desc); + + if (virt_dev->eps[ep_index].ring && + virt_dev->eps[ep_index].ring->first_seg) { + + dma_get_sgtable(dev, &sgt, + virt_dev->eps[ep_index].ring->first_seg->trbs, + virt_dev->eps[ep_index].ring->first_seg->dma, + TRB_SEGMENT_SIZE); + + *dma = virt_dev->eps[ep_index].ring->first_seg->dma; + + pa = page_to_phys(sg_page(sgt.sgl)); + sg_free_table(&sgt); + spin_unlock_irqrestore(&xhci->lock, flags); + + return pa; + } + spin_unlock_irqrestore(&xhci->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_get_xfer_resource); + +phys_addr_t xhci_get_ir_resource(struct usb_device *udev, struct xhci_interrupter *ir) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct device *dev = hcd->self.sysdev; + struct sg_table sgt; + phys_addr_t pa; + + if (!ir) + return 0; + + dma_get_sgtable(dev, &sgt, ir->event_ring->first_seg->trbs, + ir->event_ring->first_seg->dma, TRB_SEGMENT_SIZE); + + pa = page_to_phys(sg_page(sgt.sgl)); + sg_free_table(&sgt); + + return pa; +} +EXPORT_SYMBOL_GPL(xhci_get_ir_resource); + static int xhci_configure_endpoint(struct xhci_hcd *xhci, struct usb_device *udev, struct xhci_command *command, bool ctx_change, bool must_succeed); diff --git a/include/linux/usb/xhci-intr.h b/include/linux/usb/xhci-intr.h index 738b0f0481a6..d42cc9a1e698 100644 --- a/include/linux/usb/xhci-intr.h +++ b/include/linux/usb/xhci-intr.h @@ -80,7 +80,15 @@ struct xhci_interrupter { u64 s3_erst_dequeue; }; +/* Secondary interrupter */ struct xhci_interrupter * xhci_create_secondary_interrupter(struct usb_hcd *hcd, int intr_num); void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir); + +/* Offload */ +int xhci_stop_endpoint(struct usb_device *udev, + struct usb_host_endpoint *ep); +phys_addr_t xhci_get_xfer_resource(struct usb_device *udev, + struct usb_host_endpoint *ep, dma_addr_t *dma); +phys_addr_t xhci_get_ir_resource(struct usb_device *udev, struct xhci_interrupter *ir); #endif From patchwork Thu Jan 26 03:14:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48469 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69501wrn; Wed, 25 Jan 2023 19:16:56 -0800 (PST) X-Google-Smtp-Source: AK7set+kc2YQfDDjmmvqiBapTsydjc3BsQhiqBegLXyfN67Nbe8znfmLEMcoxOWUygO2nC+3iWNk X-Received: by 2002:a17:902:e185:b0:192:8502:77f9 with SMTP id y5-20020a170902e18500b00192850277f9mr367630pla.27.1674703016166; Wed, 25 Jan 2023 19:16:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703016; cv=none; d=google.com; s=arc-20160816; b=DsGAq1U37smdMFSwnyGcT8TOlsamzFEUd21UsPatQx17jrSKYgDZ8n5n3Nlkbign02 LXlDBqyg6dixRuYLAj8ahwaWeOs+5tdq5UghnQG69fsMXr7nmA15FrqEWuK331jf3PAg FVeHAT4/MJLXgrV1MUgS/Oi0QA8UmwiNM0gXWmNGWlEuv9jx92kCt7PzDvH3DZfnPPp/ Tm5GHIHW1oE1RWOVouUDan4ts5Cfguv3zq4+stN9aZmpChA9Lpqur4NgxN4WUtyG0uX6 uUufd3OKHK0qmufLi4QGQq/7yW0i00XbrbsOpS3cILA6k+cWkuLPbd7BfQbFWbdX7LTx SYuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=WFZq4UMSCH856PMLB3UVkAwA4Wl+MSgSWggJjWLXJ6A=; b=quQTBCM43DR+FSRAJQuKRRLOdViznyLn4/r6f2tJ/OmKHwrHNmjed0Z8qcx8Wgh+vK v3vME8RcYwTmqtu6hQdJZlJkDn+759etOScMSUwl9CnmLRU0iQUMGkdS7bR58os854LM 8VsPw2KPbeepFMABcT0s4Sm5VnA6tggTt9/vYfjXkGkeWOl9EO2rCj3EcXCqNvHn4Bjm 2mnSd53xUZ/qxp2bQtS46G5Dafj9vxtlh6bjTIEvx8D2WXjQYNcZxhdHRyq83AJQIUfl mBO+1LA9Xcd5nvWynqmKR2PH3JEFr8wV3O96bHQab1xgMVpCQ3TnIY1L2MX4p3UUfH0L KvOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=cWR2YZVa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id m1-20020a170902e40100b0019461098d4fsi259861ple.339.2023.01.25.19.16.44; Wed, 25 Jan 2023 19:16:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=cWR2YZVa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236278AbjAZDQL (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236227AbjAZDQF (ORCPT ); Wed, 25 Jan 2023 22:16:05 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5851065F16; Wed, 25 Jan 2023 19:15:35 -0800 (PST) Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q2rXli011227; Thu, 26 Jan 2023 03:14:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=WFZq4UMSCH856PMLB3UVkAwA4Wl+MSgSWggJjWLXJ6A=; b=cWR2YZVaU3JWSUcega+o7RXn2iak4OHL+r2PG1aBCdNhByOW4hHu8N82AFsLp8MaPi0Q 0Ysg87YlD+aDPiGxSbXsjYSL3KFHuF+GR52odkKF5W5togVwE4SUfx75tZtXDz2CDlPF dKkPugWxag8QbDjReUEncaI+YpXVvoEMlEbAaGp20p5ZjVjw9Sh9oIDBdzO+8Iyok9sL 1ayuIHaDw+JSy4P7vgaPbipcZZGeM0MSQH5PZPCywDc0LdPCaJsdie6uo/mkqnv9XNqY xj3h84l/wL+rvPtWfvYcl+9rw2K18GtDscDwlNsKoSnd7Sxb+tNGY3A0/1GqVTDROWuR 0w== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb6jc9brw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:42 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EfMI031142 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:41 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:41 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 06/22] usb: host: xhci-mem: Cleanup pending secondary event ring events Date: Wed, 25 Jan 2023 19:14:08 -0800 Message-ID: <20230126031424.14582-7-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: kDhATwC0d0NyYk1o5n1L56LWOe4NiDHT X-Proofpoint-GUID: kDhATwC0d0NyYk1o5n1L56LWOe4NiDHT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 phishscore=0 impostorscore=0 adultscore=0 priorityscore=1501 bulkscore=0 suspectscore=0 clxscore=1015 mlxscore=0 spamscore=0 mlxlogscore=616 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053389921853316?= X-GMAIL-MSGID: =?utf-8?q?1756053389921853316?= As part of xHCI bus suspend, the XHCI is halted. However, if there are pending events in the secondary event ring, it is observed that the xHCI controller stops responding to further commands upon host or device initiated bus resume. Iterate through all pending events and updating the dequeue pointer to the last pending event trb. Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci-mem.c | 74 ++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 45ac77a5d8e4..5c5266c18910 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1819,17 +1819,85 @@ int xhci_alloc_erst(struct xhci_hcd *xhci, return 0; } +static void xhci_handle_sec_intr_events(struct xhci_hcd *xhci, + struct xhci_ring *ring, struct xhci_intr_reg __iomem *ir_set, + struct xhci_erst *erst) +{ + union xhci_trb *erdp_trb, *current_trb; + struct xhci_segment *seg; + u64 erdp_reg; + u32 iman_reg; + dma_addr_t deq; + unsigned long segment_offset; + + /* disable irq, ack pending interrupt and ack all pending events */ + iman_reg = readl_relaxed(&ir_set->irq_pending); + iman_reg &= ~IMAN_IE; + writel_relaxed(iman_reg, &ir_set->irq_pending); + iman_reg = readl_relaxed(&ir_set->irq_pending); + if (iman_reg & IMAN_IP) + writel_relaxed(iman_reg, &ir_set->irq_pending); + + /* last acked event trb is in erdp reg */ + erdp_reg = xhci_read_64(xhci, &ir_set->erst_dequeue); + deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK); + if (!deq) { + xhci_dbg(xhci, "event ring handling not required\n"); + return; + } + + seg = ring->first_seg; + segment_offset = deq - seg->dma; + + /* find out virtual address of the last acked event trb */ + erdp_trb = current_trb = &seg->trbs[0] + + (segment_offset/sizeof(*current_trb)); + + /* read cycle state of the last acked trb to find out CCS */ + ring->cycle_state = le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE; + + while (1) { + /* last trb of the event ring: toggle cycle state */ + if (current_trb == &seg->trbs[TRBS_PER_SEGMENT - 1]) { + ring->cycle_state ^= 1; + current_trb = &seg->trbs[0]; + } else { + current_trb++; + } + + /* cycle state transition */ + if ((le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE) != + ring->cycle_state) + break; + } + + if (erdp_trb != current_trb) { + deq = xhci_trb_virt_to_dma(ring->deq_seg, current_trb); + if (deq == 0) + xhci_warn(xhci, + "WARN invalid SW event ring dequeue ptr.\n"); + /* Update HC event ring dequeue pointer */ + erdp_reg &= ERST_PTR_MASK; + erdp_reg |= ((u64) deq & (u64) ~ERST_PTR_MASK); + } + + /* Clear the event handler busy flag (RW1C); event ring is empty. */ + erdp_reg |= ERST_EHB; + xhci_write_64(xhci, erdp_reg, &ir_set->erst_dequeue); +} + static void xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) { struct device *dev = xhci_to_hcd(xhci)->self.sysdev; size_t erst_size; - u64 tmp64; u32 tmp; if (!ir) return; + xhci_handle_sec_intr_events(xhci, ir->event_ring, ir->ir_set, &ir->erst); + erst_size = sizeof(struct xhci_erst_entry) * (ir->erst.num_entries); if (ir->erst.entries) dma_free_coherent(dev, erst_size, @@ -1842,10 +1910,6 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) tmp &= ERST_SIZE_MASK; writel(tmp, &ir->ir_set->erst_size); - tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); - tmp64 &= (u64) ERST_PTR_MASK; - xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue); - /* free interrrupter event ring */ if (ir->event_ring) xhci_ring_free(xhci, ir->event_ring); From patchwork Thu Jan 26 03:14:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48475 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69749wrn; Wed, 25 Jan 2023 19:17:40 -0800 (PST) X-Google-Smtp-Source: AMrXdXslYegPJNPFEUOyodwI8sKXYAAwiGQpkdHC9+SQqyTX6Px2BqMLkyc0ClKkbQOKwJtyTvIY X-Received: by 2002:a05:6a20:9397:b0:b6:63c3:9b60 with SMTP id x23-20020a056a20939700b000b663c39b60mr42205815pzh.59.1674703060518; Wed, 25 Jan 2023 19:17:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703060; cv=none; d=google.com; s=arc-20160816; b=lYm1et6PvRk4t9XUJFN6G8+ddTT/v48D5acD9um2YJ6E0gs0r6w2K/IQndTrZQnkuh jpH9BOF5H2f3c6kSAeGNDl3cCRUq87VfzzIow9vKtvA+C/eT0rrDcrDN3vkQnVdcV8I6 fTKqWYCtPy1WDP8L13EXiVqoWSyj8HsG8/YfdDBmwb1V8MvBwprp+Opj+VEjnxW7mngL JSP//lH+AmWNWW7Hk9QwKEtxDHolyFM8Jl10xnHqi3yTe5JNxV8rOyufnP5sBKY6OXKU GgyH0Tf/XOiMFBaCA817NxE7hqPFgiRbligKT6lrZBAgE8duHd1NrINdX+PJzFasx3OK MG0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=qBXiNQtwFlkX5W6deQxEhKIHG8aNPycqcvlIiLU6plo=; b=i08S+nFKamLYu8sLFYXm9FG++R617H4+QzsoLNKZrlijOMsNsZPag9H2C3XVAgNCKn JMYvjxSgceVcJtgOX6Oxiue+x/c3TgNpdiZw0D1ypcMZcXoQGPD8Jw62zttmdze12Rjr uBgbx5emdbv3PU1QFFVYG8vldwiwzUSXE7UJ4ufh1Ul0laV4za+sDzywoBx6MiUP4f9m QYPddA8jLvxY6LtsSErB3fXttedvqEEDLPnH5KLkISNG791kDvY/GMnAO46AyK+PTEe9 XmXVVvg7AJ42IA7/Ft5lrfSULkx9Gl4So0eoigVDiNmUYLNlVO/CCeJRso3dt1Faxaoz zv8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Nh9CSZXq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f4-20020a637544000000b00478ea44f124si7170908pgn.96.2023.01.25.19.17.28; Wed, 25 Jan 2023 19:17:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Nh9CSZXq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236409AbjAZDQy (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236422AbjAZDQl (ORCPT ); Wed, 25 Jan 2023 22:16:41 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B64E66020; Wed, 25 Jan 2023 19:16:01 -0800 (PST) Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q3Da6b006094; Thu, 26 Jan 2023 03:14:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=qBXiNQtwFlkX5W6deQxEhKIHG8aNPycqcvlIiLU6plo=; b=Nh9CSZXqcbZC/NvDF6HxcfxTuLrye0ZOkprVKjpeQXBb/8x1V0yrhdPFWjfQRRk/GwU6 KXkRvmH2LND4TGz6t9azQUMOEg+L9MwZghDJVve7glh3NzrBnIaela7EmAPnAM7BbrJs AjATUm1VkkbIid2BBveOp7qw8SdElhhomK+2zBmPXS8yh/WME9iANSgOZbXcbpFrYL+8 qDhmu7qtslbpHwK9L3piRgpSI3IU6ixgrJMFcHlhHDiHtH9Ylvch/kapwNNdbe79cHom hXIMC6P13CZxwtN63ItCTiCFi6rUUgh1q5cZeFV3hQSkGMrtB4BBudHOFyqjFkv9sGUg gQ== Received: from nasanppmta05.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb0qrsx71-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:43 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA05.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EgdP016036 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:42 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:41 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 07/22] ASoC: Add SOC USB APIs for adding an USB backend Date: Wed, 25 Jan 2023 19:14:09 -0800 Message-ID: <20230126031424.14582-8-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: a_XQr21frpgJ8epFwFoDPKQB0M26kM23 X-Proofpoint-ORIG-GUID: a_XQr21frpgJ8epFwFoDPKQB0M26kM23 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 mlxscore=0 priorityscore=1501 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053436567514948?= X-GMAIL-MSGID: =?utf-8?q?1756053436567514948?= Some platforms may want to register its USB port to be handled by the ASoC framework. Audio playback/capture support is also handled entirely by the vendor ASoC drivers. Signed-off-by: Wesley Cheng --- include/sound/soc-usb.h | 33 +++++++ sound/soc/Makefile | 2 +- sound/soc/soc-usb.c | 202 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+), 1 deletion(-) 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..ec422a8a834f --- /dev/null +++ b/include/sound/soc-usb.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __LINUX_SND_SOC_USB_H +#define __LINUX_SND_SOC_USB_H + +/** + * struct snd_soc_usb + * @component - Reference to DAPM component + * @connection_status_cb - callback to notify connection events + * @priv_data - vendor data + **/ +struct snd_soc_usb { + struct list_head list; + struct device *dev; + struct snd_soc_component *component; + int (*connection_status_cb)(struct snd_soc_usb *usb, int card_idx, + int connected); + void *priv_data; +}; + +int snd_soc_usb_connect(struct device *usbdev, int card_idx); +int snd_soc_usb_disconnect(struct device *usbdev); +void snd_soc_usb_set_priv_data(struct device *dev, void *priv); +void *snd_soc_usb_get_priv_data(struct device *usbdev); + +struct snd_soc_usb *snd_soc_usb_add_port(struct device *dev, + int (*connection_cb)(struct snd_soc_usb *usb, int card_idx, + int connected)); +int snd_soc_usb_remove_port(struct device *dev); +#endif diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 507eaed1d6a1..3305ceb59d84 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-usb.o soc-utils.o soc-dai.o soc-component.o snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o diff --git a/sound/soc/soc-usb.c b/sound/soc/soc-usb.c new file mode 100644 index 000000000000..bfce6c9609e1 --- /dev/null +++ b/sound/soc/soc-usb.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include "../usb/card.h" + +static DEFINE_MUTEX(ctx_mutex); +static LIST_HEAD(usb_ctx_list); + +#define for_each_usb_ctx(ctx) \ + list_for_each_entry(ctx, &usb_ctx_list, 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_find_usb_ctx(struct device *dev) +{ + struct device_node *node; + struct snd_soc_usb *ctx = NULL; + + node = snd_soc_find_phandle(dev); + if (IS_ERR(node)) + return NULL; + + mutex_lock(&ctx_mutex); + for_each_usb_ctx(ctx) { + if (ctx->dev->of_node == node) { + of_node_put(node); + mutex_unlock(&ctx_mutex); + return ctx; + } + } + of_node_put(node); + mutex_unlock(&ctx_mutex); + + return NULL; +} + +/** + * snd_soc_usb_get_priv_data() - Retrieve private data stored + * @usbdev: USB bus sysdev + * + * Fetch the private data stored in the USB SND SOC structure. This is + * intended to be called by the USB offloading class driver, in order to + * attain parameters about the USB backend device. + * + */ +void *snd_soc_usb_get_priv_data(struct device *usbdev) +{ + struct snd_soc_usb *ctx; + + if (!usbdev) + return NULL; + + ctx = snd_soc_find_usb_ctx(usbdev); + + return ctx ? ctx->priv_data : NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_get_priv_data); + +/** + * snd_soc_usb_set_priv_data() - Set private data stored + * @dev: USB backend device + * @priv: private data to store + * + * Save data describing the USB backend device parameters. This is intended + * to be called by the ASoC USB backend driver. + * + */ +void snd_soc_usb_set_priv_data(struct device *dev, void *priv) +{ + struct snd_soc_usb *ctx; + + mutex_lock(&ctx_mutex); + for_each_usb_ctx(ctx) { + if (dev->of_node == ctx->dev->of_node) { + ctx->priv_data = priv; + break; + } + } + mutex_unlock(&ctx_mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_usb_set_priv_data); + +/** + * snd_soc_usb_add_port() - Add a USB backend port + * @dev: USB backend device + * @connection_cb: connection status callback + * + * Register a USB backend device to the SND USB SOC framework. Memory is + * allocated as part of the USB backend device. + * + */ +struct snd_soc_usb *snd_soc_usb_add_port(struct device *dev, + int (*connection_cb)(struct snd_soc_usb *usb, int card_idx, + int connected)) +{ + struct snd_soc_usb *usb; + + usb = devm_kzalloc(dev, sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + usb->connection_status_cb = connection_cb; + usb->dev = dev; + + mutex_lock(&ctx_mutex); + list_add_tail(&usb->list, &usb_ctx_list); + mutex_unlock(&ctx_mutex); + + return usb; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_add_port); + +/** + * snd_soc_usb_remove_port() - Remove a USB backend port + * @dev: USB backend device + * + * Remove a USB backend device from USB SND SOC. Memory is freed when USB + * backend is removed. + * + */ +int snd_soc_usb_remove_port(struct device *dev) +{ + struct snd_soc_usb *ctx, *tmp; + + mutex_lock(&ctx_mutex); + list_for_each_entry_safe(ctx, tmp, &usb_ctx_list, list) { + if (ctx->dev == dev) { + list_del(&ctx->list); + break; + } + } + mutex_unlock(&ctx_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_remove_port); + +/** + * snd_soc_usb_connect() - Notification of USB device connection + * @usbdev: USB bus device + * @card_idx: USB SND card instance + * + * Notify of a new USB SND device connection. The card_idx can be used to + * handle how the USB backend selects, which device to enable offloading on. + * + */ +int snd_soc_usb_connect(struct device *usbdev, int card_idx) +{ + struct snd_soc_usb *ctx; + + if (!usbdev) + return -ENODEV; + + ctx = snd_soc_find_usb_ctx(usbdev); + if (!ctx) + return -ENODEV; + + if (ctx->connection_status_cb) + ctx->connection_status_cb(ctx, card_idx, 1); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_connect); + +/** + * snd_soc_usb_connect() - Notification of USB device connection + * @usbdev: USB bus device + * + * Notify of a new USB SND device disconnection to the USB backend. + * + */ +int snd_soc_usb_disconnect(struct device *usbdev) +{ + struct snd_soc_usb *ctx; + + if (!usbdev) + return -ENODEV; + + ctx = snd_soc_find_usb_ctx(usbdev); + if (!ctx) + return -ENODEV; + + if (ctx->connection_status_cb) + ctx->connection_status_cb(ctx, -1, 0); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_usb_disconnect); From patchwork Thu Jan 26 03:14:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48473 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69644wrn; Wed, 25 Jan 2023 19:17:19 -0800 (PST) X-Google-Smtp-Source: AMrXdXuHBbVEndGidLnyJ9EHCmpndzcOdgxJMAawQaQ32n9DTlHT6squtUxnKoflMMl23I0VDxCO X-Received: by 2002:a05:6a20:b71c:b0:b4:f66a:99a9 with SMTP id fg28-20020a056a20b71c00b000b4f66a99a9mr31596002pzb.60.1674703038975; Wed, 25 Jan 2023 19:17:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703038; cv=none; d=google.com; s=arc-20160816; b=W+VSKfsP8oGHMd2A04MGoYHWhcWfjVEwNDwse0OxFVVMln2Si34m84MWpGU2iq1nH6 UYscUBRohjvAKWJNnW8cfJaJHaAh3dtid7leg/f9mNBYZe8+9AYvuyWm2zz3ZGE0NJVe RuceOf4zsv/slJIz6BA4nGQ6VoKhDQzj73BwpDD5rZk499dSUJkyej4RaEzGEJPPupWJ XLGIrsAkKqTMdATLYjuJeLwr7cJc83RJxIAhp+J1e8wuPn+v1ujaVYkoUbI8NJbiCnoy KrBT+NYjmFqltdUYQCqqgTPTGuKBO7bX81WlKjiSfZMa+Tv6XZFQ4RVC99q900zxxQ9U 2n9Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=A/BKgbbHZpSa0qF5KMGg4PEhnJ5z9CMMjnv3GKZjGVs=; b=CP3MCIP7rPcz2C9UiUti2oua+sjjtcAXSJaDBjKVQyKuIjznn41rcvYPQXb+zqOny/ lTvmE+fVN+iaU9PoKI8/2GUWnmiDKRk4225PXF0Yo/bkVhB1uipEnZa6aB3MYwECkAw3 QyDiVjVxyVipm26WoWrPof0p/k9odEAE9iaYKe0YZf8UvlU1KHD+LaUp1S0Sk90R122I G0dkPIZeBRGnbvdOKzY1gsYiK7berpbzEfnD8Oi+kouYhl8wo2bBznGm96UbzjJ0YU+f rkw/v1iNH/9HILERix+jZ9HGjUshtPcJsityooNnfBlN874LD/jcohEDsbKM9YomIw9H e61w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Y2LihmmL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f4-20020a637544000000b00477ca5b5617si7108334pgn.147.2023.01.25.19.17.06; Wed, 25 Jan 2023 19:17:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Y2LihmmL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236338AbjAZDQo (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46680 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236378AbjAZDQ3 (ORCPT ); Wed, 25 Jan 2023 22:16:29 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 690CE65EFA; Wed, 25 Jan 2023 19:15:54 -0800 (PST) Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q2xRTJ030587; Thu, 26 Jan 2023 03:14:43 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=A/BKgbbHZpSa0qF5KMGg4PEhnJ5z9CMMjnv3GKZjGVs=; b=Y2LihmmLFBF++Py8oWLnEjFitR70rZzI26FY9dPmTKtKgYaSibPseR5obnhWct1U/c0n hDqyACf7LtKnTFm6gTv/EQ6Xi08ejGTr5F33qAQVfevNbutg6TEp2/KiEXV/JnGcHIwn LV2zM54P0qAbwqBz4oQtfopu79Obk/e55o1J7VbEVw36+tb4Oza7YPbEndwmj/+3g2JF juJsrzMezEDz3cR2Z5bHIqeUD6EqOMWCd5Da5y4XV8yrKD1HaIdMYfdYRLOns8ROkomU IZynoOp6aoEzPUPhc1wlAJV6lbNOCVwWXYsvvjtqp6/ZBaQGFGO2OdDbwjDb10J8ypxD Eg== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb0qrsx72-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:43 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EhhH011777 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:43 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:42 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 08/22] ASoC: dt-bindings: Add USB_RX port Date: Wed, 25 Jan 2023 19:14:10 -0800 Message-ID: <20230126031424.14582-9-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: XHGwBGVDQzkBlp1xS5NgCuesaQV-qD0R X-Proofpoint-ORIG-GUID: XHGwBGVDQzkBlp1xS5NgCuesaQV-qD0R X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=637 malwarescore=0 mlxscore=0 priorityscore=1501 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053413458309653?= X-GMAIL-MSGID: =?utf-8?q?1756053413458309653?= Q6DSP supports handling of USB playback audio data if USB audio offloading is enabled. Add a new definition for the USB_RX AFE port, which is referenced when the AFE port is started. Signed-off-by: Wesley Cheng Acked-by: Krzysztof Kozlowski --- include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h index 9f7c5103bc82..746bc462bb2e 100644 --- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h +++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h @@ -131,6 +131,7 @@ #define RX_CODEC_DMA_RX_7 126 #define QUINARY_MI2S_RX 127 #define QUINARY_MI2S_TX 128 +#define USB_RX 129 #define LPASS_CLK_ID_PRI_MI2S_IBIT 1 #define LPASS_CLK_ID_PRI_MI2S_EBIT 2 From patchwork Thu Jan 26 03:14:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48463 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69246wrn; Wed, 25 Jan 2023 19:15:59 -0800 (PST) X-Google-Smtp-Source: AMrXdXu/lPbzqpteeMFqzw3DqTeZG80OgB3rUxemcZ+JSpvKA1AbDe0mzja5UwGXnLfJjN1TSxbl X-Received: by 2002:a17:90a:355:b0:22b:aa69:ccc7 with SMTP id 21-20020a17090a035500b0022baa69ccc7mr23184710pjf.27.1674702958733; Wed, 25 Jan 2023 19:15:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702958; cv=none; d=google.com; s=arc-20160816; b=kNnCarNR5RJXpzBzy08kUYIrpVRdZ78wfAnTxBg2UH7l1wKauypXDUNaGokLUdylcV PNXX2q728FfKB4c6cX4lnyxx4Ildzh9ITLaBZNDJV95mqJZ/9GIlCOQlmrr2ksByFvID aAv+BJMgIwMlvyIBf5Fstnp/D1DZJSZFjfRg1S9ZybpnBaMYqA5T02Ew+f5esvYM2EjV qjNED738BgFUEv2tm4J7kM6vI4U5HsxExIwkpGRt4D1RUX28eZ4DDkfY6Jz2GvEf/lP5 U86og0B2nqiTm+QApLwnjYvAOqqZeeJLjq6w1CkbbIzBW+AN+kLRpFdtW8znNRTRK084 CPCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=FHMen8BOj1wJyxQLpH56jMvwuqHzmMsYn9QZTPIZBcI=; b=XOE2t8EHMavICMUjG3WXmN1V22vZB8/Dssfta7zNdfpYxwF1eTdfTFZDKeScBhvUWw ZdnyrYTEXHDniy3DmY4F8GVbBDHlAhY3gTNHZP+L0T6uZtvbus7W2s/o/TUDTC2F1mfe 3XbEFhgDY8jVrxYPLTW0Vh5TjmyGtsjpOZCwhpGIN0as9iEBQ0+aE4BQHoc607zZmSOp Y+EB2/3oDIIh93XQXaubrY5znHY8gV4mjd2MiSMksyZWFHWxYv+6fqyJhSa1FznV/o5F 4jiTZ7ajnpE36Oqb3EatD0kyF8wckoJbv6t2sbCx3G7Rx9ha4t7kw13XgaHBGKzn1v1E T4xw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=YkNnansA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 22-20020a17090a0b9600b00200435da17asi3520055pjr.128.2023.01.25.19.15.46; Wed, 25 Jan 2023 19:15:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=YkNnansA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236171AbjAZDO6 (ORCPT + 99 others); Wed, 25 Jan 2023 22:14:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235962AbjAZDOt (ORCPT ); Wed, 25 Jan 2023 22:14:49 -0500 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F41265F09; Wed, 25 Jan 2023 19:14:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702885; x=1706238885; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=FHMen8BOj1wJyxQLpH56jMvwuqHzmMsYn9QZTPIZBcI=; b=YkNnansAfGMcf29uscFHUV+OvP8SykYg6EgvjF5wGAJ5vHh3ePP6fwCb uOs5QyijKK/VLZGCOGDT9Z5PTOpRQ7RiGvH/Di0oqQR3EZ8D2eEGsP7Z4 R2IZO51f4uM5q3oVH78YjM5cl3u2uEllRFW+HgaLMJMNOXx27eZyr5Ixi Q=; Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-02.qualcomm.com with ESMTP; 25 Jan 2023 19:14:43 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg-SD-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:43 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:42 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 09/22] ASoC: qcom: qdsp6: Introduce USB AFE port to q6dsp Date: Wed, 25 Jan 2023 19:14:11 -0800 Message-ID: <20230126031424.14582-10-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053329904425669?= X-GMAIL-MSGID: =?utf-8?q?1756053329904425669?= The QC ADSP is able to support USB playback endpoints, so that the main application processor can be placed into lower CPU power modes. This adds the required AFE port configurations and port start command to start an audio session. Specifically, the QC ADSP can support all potential endpoints that are exposed by the audio data interface. This includes, feedback endpoints (both implicit and explicit) as well as the isochronous (data) endpoints. The size of audio samples sent per USB frame (microframe) will be adjusted based on information received on the feedback endpoint. Signed-off-by: Wesley Cheng --- sound/soc/qcom/qdsp6/q6afe-dai.c | 48 ++++++ sound/soc/qcom/qdsp6/q6afe.c | 183 +++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 46 +++++- sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 23 +++ sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h | 1 + sound/soc/qcom/qdsp6/q6routing.c | 8 + 6 files changed, 308 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 8bb7452b8f18..0773a0882d9b 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -111,6 +111,40 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream, return 0; } +static int q6usb_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + int channels = params_channels(params); + int rate = params_rate(params); + struct q6afe_usb_cfg *usb = &dai_data->port_config[dai->id].usb_audio; + + usb->sample_rate = rate; + usb->num_channels = channels; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_SPECIAL: + usb->bit_width = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_3LE: + usb->bit_width = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + usb->bit_width = 32; + break; + default: + dev_err(dai->dev, "%s: invalid format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + return 0; +} + static int q6i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -411,6 +445,10 @@ static int q6afe_dai_prepare(struct snd_pcm_substream *substream, q6afe_cdc_dma_port_prepare(dai_data->port[dai->id], &dai_data->port_config[dai->id].dma_cfg); break; + case USB_RX: + q6afe_usb_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].usb_audio); + break; default: return -EINVAL; } @@ -495,6 +533,8 @@ static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai, } static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { + /* USB playback AFE port receives data for playback, hence use the RX port */ + {"USB Playback", NULL, "USB_RX"}, {"HDMI Playback", NULL, "HDMI_RX"}, {"Display Port Playback", NULL, "DISPLAY_PORT_RX"}, {"Slimbus Playback", NULL, "SLIMBUS_0_RX"}, @@ -639,6 +679,12 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { {"RX_CODEC_DMA_RX_7 Playback", NULL, "RX_CODEC_DMA_RX_7"}, }; +static const struct snd_soc_dai_ops q6usb_ops = { + .prepare = q6afe_dai_prepare, + .hw_params = q6usb_hw_params, + .shutdown = q6afe_dai_shutdown, +}; + static const struct snd_soc_dai_ops q6hdmi_ops = { .prepare = q6afe_dai_prepare, .hw_params = q6hdmi_hw_params, @@ -703,6 +749,7 @@ static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai) } static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { + SND_SOC_DAPM_AIF_IN("USB_RX", NULL, 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, SND_SOC_NOPM, 0, 0), @@ -1068,6 +1115,7 @@ static int q6afe_dai_dev_probe(struct platform_device *pdev) cfg.q6i2s_ops = &q6i2s_ops; cfg.q6tdm_ops = &q6tdm_ops; cfg.q6dma_ops = &q6dma_ops; + cfg.q6usb_ops = &q6usb_ops; dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais); return devm_snd_soc_register_component(dev, &q6afe_dai_component, dais, num_dais); diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 919e326b9462..ca799fc3820e 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -34,6 +34,8 @@ #define AFE_MODULE_TDM 0x0001028A #define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG 0x00010235 +#define AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS 0x000102A5 +#define AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT 0x000102AA #define AFE_PARAM_ID_LPAIF_CLK_CONFIG 0x00010238 #define AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG 0x00010239 @@ -43,6 +45,7 @@ #define AFE_PARAM_ID_TDM_CONFIG 0x0001029D #define AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG 0x00010297 #define AFE_PARAM_ID_CODEC_DMA_CONFIG 0x000102B8 +#define AFE_PARAM_ID_USB_AUDIO_CONFIG 0x000102A4 #define AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST 0x000100f4 #define AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST 0x000100f5 #define AFE_CMD_REMOTE_LPASS_CORE_HW_DEVOTE_REQUEST 0x000100f6 @@ -71,12 +74,16 @@ #define AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL 0x1 #define AFE_LINEAR_PCM_DATA 0x0 +#define AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG 0x1 /* Port IDs */ #define AFE_API_VERSION_HDMI_CONFIG 0x1 #define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E #define AFE_PORT_ID_HDMI_OVER_DP_RX 0x6020 +/* USB AFE port */ +#define AFE_PORT_ID_USB_RX 0x7000 + #define AFE_API_VERSION_SLIMBUS_CONFIG 0x1 /* Clock set API version */ #define AFE_API_VERSION_CLOCK_SET 1 @@ -512,12 +519,109 @@ struct afe_param_id_cdc_dma_cfg { u16 active_channels_mask; } __packed; +struct afe_param_id_usb_cfg { +/* Minor version used for tracking USB audio device configuration. + * Supported values: AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG + */ + u32 cfg_minor_version; +/* Sampling rate of the port. + * Supported values: + * - AFE_PORT_SAMPLE_RATE_8K + * - AFE_PORT_SAMPLE_RATE_11025 + * - AFE_PORT_SAMPLE_RATE_12K + * - AFE_PORT_SAMPLE_RATE_16K + * - AFE_PORT_SAMPLE_RATE_22050 + * - AFE_PORT_SAMPLE_RATE_24K + * - AFE_PORT_SAMPLE_RATE_32K + * - AFE_PORT_SAMPLE_RATE_44P1K + * - AFE_PORT_SAMPLE_RATE_48K + * - AFE_PORT_SAMPLE_RATE_96K + * - AFE_PORT_SAMPLE_RATE_192K + */ + u32 sample_rate; +/* Bit width of the sample. + * Supported values: 16, 24 + */ + u16 bit_width; +/* Number of channels. + * Supported values: 1 and 2 + */ + u16 num_channels; +/* Data format supported by the USB. The supported value is + * 0 (#AFE_USB_AUDIO_DATA_FORMAT_LINEAR_PCM). + */ + u16 data_format; +/* this field must be 0 */ + u16 reserved; +/* device token of actual end USB aduio device */ + u32 dev_token; +/* endianness of this interface */ + u32 endian; +/* service interval */ + u32 service_interval; +} __packed; + +/** + * struct afe_param_id_usb_audio_dev_params + * @cfg_minor_version: Minor version used for tracking USB audio device + * configuration. + * Supported values: + * AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG + * @dev_token: device token of actual end USB aduio device + **/ +struct afe_param_id_usb_audio_dev_params { + u32 cfg_minor_version; + u32 dev_token; +} __packed; + +/** + * struct afe_param_id_usb_audio_dev_lpcm_fmt + * @cfg_minor_version: Minor version used for tracking USB audio device + * configuration. + * Supported values: + * AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG + * @endian: endianness of this interface + **/ +struct afe_param_id_usb_audio_dev_lpcm_fmt { + u32 cfg_minor_version; + u32 endian; +} __packed; + +/** + * struct afe_param_id_usb_audio_dev_latency_mode + * @cfg_minor_version: Minor version used for tracking USB audio device + * configuration. + * Supported values: + * AFE_API_MINOR_VERSION_USB_AUDIO_LATENCY_MODE + * @mode: latency mode for the USB audio device + **/ +struct afe_param_id_usb_audio_dev_latency_mode { + u32 minor_version; + u32 mode; +} __packed; + +#define AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL 0x000102B7 + +/** + * struct afe_param_id_usb_audio_svc_interval + * @cfg_minor_version: Minor version used for tracking USB audio device + * configuration. + * Supported values: + * AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG + * @svc_interval: service interval + **/ +struct afe_param_id_usb_audio_svc_interval { + u32 cfg_minor_version; + u32 svc_interval; +} __packed; + union afe_port_config { struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch; struct afe_param_id_slimbus_cfg slim_cfg; struct afe_param_id_i2s_cfg i2s_cfg; struct afe_param_id_tdm_cfg tdm_cfg; struct afe_param_id_cdc_dma_cfg dma_cfg; + struct afe_param_id_usb_cfg usb_cfg; } __packed; @@ -577,6 +681,7 @@ struct afe_port_map { */ static struct afe_port_map port_maps[AFE_PORT_MAX] = { + [USB_RX] = { AFE_PORT_ID_USB_RX, USB_RX, 1, 1}, [HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX, HDMI_RX, 1, 1}, [SLIMBUS_0_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX, SLIMBUS_0_RX, 1, 1}, @@ -1289,6 +1394,82 @@ void q6afe_tdm_port_prepare(struct q6afe_port *port, } EXPORT_SYMBOL_GPL(q6afe_tdm_port_prepare); +static int afe_port_send_usb_dev_param(struct q6afe_port *port, struct q6afe_usb_cfg *cfg) +{ + union afe_port_config *pcfg = &port->port_cfg; + struct afe_param_id_usb_audio_dev_params usb_dev; + struct afe_param_id_usb_audio_dev_lpcm_fmt lpcm_fmt; + struct afe_param_id_usb_audio_svc_interval svc_int; + int ret = 0; + + if (!pcfg) { + dev_err(port->afe->dev, "%s: Error, no configuration data\n", __func__); + ret = -EINVAL; + goto exit; + } + + memset(&usb_dev, 0, sizeof(usb_dev)); + memset(&lpcm_fmt, 0, sizeof(lpcm_fmt)); + + usb_dev.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG; + q6afe_port_set_param_v2(port, &usb_dev, + AFE_PARAM_ID_USB_AUDIO_DEV_PARAMS, + AFE_MODULE_AUDIO_DEV_INTERFACE, sizeof(usb_dev)); + if (ret) { + dev_err(port->afe->dev, "%s: AFE device param cmd failed %d\n", + __func__, ret); + goto exit; + } + + lpcm_fmt.cfg_minor_version = AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG; + lpcm_fmt.endian = pcfg->usb_cfg.endian; + ret = q6afe_port_set_param_v2(port, &lpcm_fmt, + AFE_PARAM_ID_USB_AUDIO_DEV_LPCM_FMT, + AFE_MODULE_AUDIO_DEV_INTERFACE, sizeof(lpcm_fmt)); + if (ret) { + dev_err(port->afe->dev, "%s: AFE device param cmd LPCM_FMT failed %d\n", + __func__, ret); + goto exit; + } + + svc_int.cfg_minor_version = + AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG; + svc_int.svc_interval = pcfg->usb_cfg.service_interval; + ret = q6afe_port_set_param_v2(port, &svc_int, + AFE_PARAM_ID_USB_AUDIO_SVC_INTERVAL, + AFE_MODULE_AUDIO_DEV_INTERFACE, sizeof(svc_int)); + if (ret) { + dev_err(port->afe->dev, "%s: AFE device param cmd svc_interval failed %d\n", + __func__, ret); + ret = -EINVAL; + goto exit; + } +exit: + return ret; +} + +/** + * q6afe_usb_port_prepare() - Prepare usb afe port. + * + * @port: Instance of afe port + * @cfg: USB configuration for the afe port + * + */ +void q6afe_usb_port_prepare(struct q6afe_port *port, + struct q6afe_usb_cfg *cfg) +{ + union afe_port_config *pcfg = &port->port_cfg; + + pcfg->usb_cfg.cfg_minor_version = + AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG; + pcfg->usb_cfg.sample_rate = cfg->sample_rate; + pcfg->usb_cfg.num_channels = cfg->num_channels; + pcfg->usb_cfg.bit_width = cfg->bit_width; + + afe_port_send_usb_dev_param(port, cfg); +} +EXPORT_SYMBOL_GPL(q6afe_usb_port_prepare); + /** * q6afe_hdmi_port_prepare() - Prepare hdmi afe port. * @@ -1611,6 +1792,8 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) break; case AFE_PORT_ID_WSA_CODEC_DMA_RX_0 ... AFE_PORT_ID_RX_CODEC_DMA_RX_7: cfg_type = AFE_PARAM_ID_CODEC_DMA_CONFIG; + case AFE_PORT_ID_USB_RX: + cfg_type = AFE_PARAM_ID_USB_AUDIO_CONFIG; break; default: dev_err(dev, "Invalid port id 0x%x\n", port_id); diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 30fd77e2f458..88550a08e57d 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -5,7 +5,7 @@ #include -#define AFE_PORT_MAX 129 +#define AFE_PORT_MAX 130 #define MSM_AFE_PORT_TYPE_RX 0 #define MSM_AFE_PORT_TYPE_TX 1 @@ -205,6 +205,47 @@ struct q6afe_cdc_dma_cfg { u16 active_channels_mask; }; +/** + * struct q6afe_usb_cfg + * @cfg_minor_version: Minor version used for tracking USB audio device + * configuration. + * Supported values: + * AFE_API_MINOR_VERSION_USB_AUDIO_CONFIG + * @sample_rate: Sampling rate of the port + * Supported values: + * AFE_PORT_SAMPLE_RATE_8K + * AFE_PORT_SAMPLE_RATE_11025 + * AFE_PORT_SAMPLE_RATE_12K + * AFE_PORT_SAMPLE_RATE_16K + * AFE_PORT_SAMPLE_RATE_22050 + * AFE_PORT_SAMPLE_RATE_24K + * AFE_PORT_SAMPLE_RATE_32K + * AFE_PORT_SAMPLE_RATE_44P1K + * AFE_PORT_SAMPLE_RATE_48K + * AFE_PORT_SAMPLE_RATE_96K + * AFE_PORT_SAMPLE_RATE_192K + * @bit_width: Bit width of the sample. + * Supported values: 16, 24 + * @num_channels: Number of channels + * Supported values: 1, 2 + * @data_format: Data format supported by the USB + * Supported values: 0 + * @reserved: this field must be 0 + * @dev_token: device token of actual end USB aduio device + * @endian: endianness of this interface + * @service_interval: service interval + **/ +struct q6afe_usb_cfg { + u32 cfg_minor_version; + u32 sample_rate; + u16 bit_width; + u16 num_channels; + u16 data_format; + u16 reserved; + u32 dev_token; + u32 endian; + u32 service_interval; +}; struct q6afe_port_config { struct q6afe_hdmi_cfg hdmi; @@ -212,6 +253,7 @@ struct q6afe_port_config { struct q6afe_i2s_cfg i2s_cfg; struct q6afe_tdm_cfg tdm; struct q6afe_cdc_dma_cfg dma_cfg; + struct q6afe_usb_cfg usb_audio; }; struct q6afe_port; @@ -221,6 +263,8 @@ int q6afe_port_start(struct q6afe_port *port); int q6afe_port_stop(struct q6afe_port *port); void q6afe_port_put(struct q6afe_port *port); int q6afe_get_port_id(int index); +void q6afe_usb_port_prepare(struct q6afe_port *port, + struct q6afe_usb_cfg *cfg); void q6afe_hdmi_port_prepare(struct q6afe_port *port, struct q6afe_hdmi_cfg *cfg); void q6afe_slim_port_prepare(struct q6afe_port *port, diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c index f67c16fd90b9..39719c3f1767 100644 --- a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c +++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c @@ -81,6 +81,26 @@ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = { + { + .playback = { + .stream_name = "USB Playback", + .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_min = 8000, + .rate_max = 192000, + }, + .id = USB_RX, + .name = "USB_RX", + }, { .playback = { .stream_name = "HDMI Playback", @@ -616,6 +636,9 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev, case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7: q6dsp_audio_fe_dais[i].ops = cfg->q6dma_ops; break; + case USB_RX: + q6dsp_audio_fe_dais[i].ops = cfg->q6usb_ops; + break; default: break; } diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h index 7f052c8a1257..d8dde6dd0aca 100644 --- a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h +++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.h @@ -11,6 +11,7 @@ struct q6dsp_audio_port_dai_driver_config { const struct snd_soc_dai_ops *q6i2s_ops; const struct snd_soc_dai_ops *q6tdm_ops; const struct snd_soc_dai_ops *q6dma_ops; + const struct snd_soc_dai_ops *q6usb_ops; }; struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev, diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 928fd23e2c27..683ae2ae8e50 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -514,6 +514,9 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, return 1; } +static const struct snd_kcontrol_new usb_mixer_controls[] = { + Q6ROUTING_RX_MIXERS(USB_RX) }; + static const struct snd_kcontrol_new hdmi_mixer_controls[] = { Q6ROUTING_RX_MIXERS(HDMI_RX) }; @@ -733,6 +736,10 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { /* Mixer definitions */ + SND_SOC_DAPM_MIXER("USB Mixer", SND_SOC_NOPM, 0, 0, + usb_mixer_controls, + ARRAY_SIZE(usb_mixer_controls)), + SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)), @@ -952,6 +959,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { + Q6ROUTING_RX_DAPM_ROUTE("USB Mixer", "USB_RX"), Q6ROUTING_RX_DAPM_ROUTE("HDMI Mixer", "HDMI_RX"), Q6ROUTING_RX_DAPM_ROUTE("DISPLAY_PORT_RX Audio Mixer", "DISPLAY_PORT_RX"), From patchwork Thu Jan 26 03:14:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48477 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp70127wrn; Wed, 25 Jan 2023 19:18:55 -0800 (PST) X-Google-Smtp-Source: AMrXdXu+ervRWVk7qQNyrwmKWzmpRYt0jx57yTarr2dPEqvAw6u3aKgRF+CSd493qHjFVPDnvW0m X-Received: by 2002:a17:906:48cb:b0:86d:d334:b90b with SMTP id d11-20020a17090648cb00b0086dd334b90bmr36243972ejt.67.1674703135098; Wed, 25 Jan 2023 19:18:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703135; cv=none; d=google.com; s=arc-20160816; b=ExQa31UCpJ+GuVlBWPGAR8OPUqAE1YSOL4pKdLUjmh6B+lC4MrHu3xhEsUJiHKMD/A CmcoI+4lQmb7I+IQZMeFnykEJjFESzzGpUwkJ1NRHRD9FxmhcY5WQaJGrJPJjoL22mOv wEsVxX1nJRtISGyULc6WQFHhE1uabqlRWD1BvC6/8BWmndbiw83/ll/VNaC/zjhdEr0P o8gGd98PCe0qN5E6dBjlEA9eUpEYPv0tfvK/HW5eOGfwrLxnTCuxDLYpKheWyt3lXR0+ q+BM5H86qzdfA/eavM5/fMki57pwqmhPT9pgmXWhtb48o4KgfJmWw16htONX/jS/rVeq 3W2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Adk1/F5AFhB4MjrOMT9puVK7WazS1Fzr8KJMP5s4uLE=; b=aFRyu+ax/jHbv1hZ/Xc3cZBOZvS0H2RfB/5utQPwAM1axOdBl5qZVRWeKeBDYNTUsT rldhZYb37nO+YcJNRsCF+psKNIT/mNnF4i856SI545WjzKs7a112sS6OsUymk7D2OJIl ae/W2HsvsCI2/D7Z49a0X9cdKBPD6LuuvXKvNvQZs1U2Cp/pC7FKEVbex+nEX93qHUOo TipVDgjyqtV2TlMmGfKGg6psiQdOKKq0D4Bf1fu+l13JjnMGSAEqh6ZUiVtibUEVIbLv IwIZR2+3sJnJbBrbuy23XKjjz4YDm9obvYXldQbCVYg8O54R9gcn06MQgTScamlKOKeS 9wgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=XIhaJS5D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id fl4-20020a1709072a8400b007c173f77500si7138344ejc.427.2023.01.25.19.18.31; Wed, 25 Jan 2023 19:18:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=XIhaJS5D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229543AbjAZDQ4 (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236373AbjAZDQn (ORCPT ); Wed, 25 Jan 2023 22:16:43 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23A3166037; Wed, 25 Jan 2023 19:16:05 -0800 (PST) Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q30Bfg032691; Thu, 26 Jan 2023 03:14:45 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=Adk1/F5AFhB4MjrOMT9puVK7WazS1Fzr8KJMP5s4uLE=; b=XIhaJS5DvRx7iQRXN50Sj4ck+7SoAoCzQOBV1Al0mBlWF6Z8jD4s8zMz+lvKwTzStbXZ aK/OMEVkIuPPFUWgqMyWorou9nKl9jF4xUhLjOLPIC1ewAtOJSCJYsUSZzCKj4UPJsL1 iy6PO2LPLDv9FSIUuwY0TGsbCc13jvDmpIKg/HPvWnpy3NTkZL5V2uKuBJtxRjQJjUyY jggG8t5gZGnp41R3bPY/wACjeUl+yvADY6IC2VfIy5jhEX9WceLA2syVu8TDp6OvbsP/ eSMRJi4Jmu3U2AACSchSXfPpceKHg37sXP/TZ4yotHqv0PNIRwYtWUWQO/XQzGJUxoWL 1Q== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb0qrsx76-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:45 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EiRC031320 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:44 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:44 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 11/22] ASoC: qcom: Add USB backend ASoC driver for Q6 Date: Wed, 25 Jan 2023 19:14:13 -0800 Message-ID: <20230126031424.14582-12-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: p0q8Vl-4EB34Ouuz9Pl0uvLkdIMrHrgi X-Proofpoint-ORIG-GUID: p0q8Vl-4EB34Ouuz9Pl0uvLkdIMrHrgi X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=999 malwarescore=0 mlxscore=0 priorityscore=1501 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053514389066020?= X-GMAIL-MSGID: =?utf-8?q?1756053514389066020?= 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. Signed-off-by: Wesley Cheng --- include/sound/q6usboffload.h | 20 +++ sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6usb.c | 231 ++++++++++++++++++++++++++++++++++ 4 files changed, 256 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..e576808901d9 --- /dev/null +++ b/include/sound/q6usboffload.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * linux/sound/q6usboffload.h -- QDSP6 USB offload + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/** + * struct q6usb_offload + * @dev - dev handle to usb be + * @sid - streamID for iommu + * @intr_num - usb interrupter number + * @domain - allocated iommu domain + **/ +struct q6usb_offload { + struct device *dev; + u32 sid; + u32 intr_num; + struct iommu_domain *domain; +}; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 8c7398bc1ca8..d65c365116e5 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -111,6 +111,9 @@ config SND_SOC_QDSP6_APM config SND_SOC_QDSP6_PRM_LPASS_CLOCKS tristate +config SND_SOC_QDSP6_USB + tristate + config SND_SOC_QDSP6_PRM tristate select SND_SOC_QDSP6_PRM_LPASS_CLOCKS @@ -131,6 +134,7 @@ config SND_SOC_QDSP6 select SND_SOC_TOPOLOGY select SND_SOC_QDSP6_APM select SND_SOC_QDSP6_PRM + select SND_SOC_QDSP6_USB help To add support for MSM QDSP6 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 3963bf234664..c9457ee898d0 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..afbff66108bc --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "q6dsp-lpass-ports.h" +#include "q6afe.h" + +struct q6usb_port_data { + struct q6afe_usb_cfg usb_cfg; + struct snd_soc_usb *usb; + struct q6usb_offload priv; + int active_idx; +}; + +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) +{ + return 0; +} +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_component_probe(struct snd_soc_component *component) +{ + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + + data->usb->component = component; + + snd_soc_dapm_disable_pin(dapm, "USB_RX_BE"); + snd_soc_dapm_sync(dapm); + + return 0; +} + +static const struct snd_soc_component_driver q6usb_dai_component = { + .probe = q6usb_component_probe, + .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_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx, + int connected) +{ + struct snd_soc_dapm_context *dapm; + struct q6usb_port_data *data; + + /* Check if routes to the backend have not yet been established */ + if (!usb->component) + return -ENODEV; + + dapm = snd_soc_component_get_dapm(usb->component); + data = dev_get_drvdata(usb->component->dev); + + if (connected) { + snd_soc_dapm_enable_pin(dapm, "USB_RX_BE"); + /* We only track the latest USB headset plugged in */ + data->active_idx = card_idx; + } else { + snd_soc_dapm_disable_pin(dapm, "USB_RX_BE"); + } + snd_soc_dapm_sync(dapm); + + return 0; +} + +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; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_property_read_u32(node, "qcom,usb-audio-stream-id", + &data->priv.sid); + if (ret) { + dev_err(&pdev->dev, "failed to read sid.\n"); + return -ENODEV; + } + + ret = of_property_read_u32(node, "qcom,usb-audio-intr-num", + &data->priv.intr_num); + if (ret) { + dev_err(&pdev->dev, "failed to read intr num.\n"); + return -ENODEV; + } + + data->priv.domain = iommu_domain_alloc(pdev->dev.bus); + if (!data->priv.domain) { + dev_err(&pdev->dev, "failed to allocate iommu domain\n"); + return -ENODEV; + } + + /* attach to external processor iommu */ + ret = iommu_attach_device(data->priv.domain, &pdev->dev); + if (ret) { + dev_err(&pdev->dev, "failed to attach device ret = %d\n", ret); + goto free_domain; + } + + data->usb = snd_soc_usb_add_port(dev, q6usb_alsa_connection_cb); + if (IS_ERR(data->usb)) { + dev_err(&pdev->dev, "failed to add usb port\n"); + goto detach_device; + } + + data->priv.dev = dev; + dev_set_drvdata(dev, data); + devm_snd_soc_register_component(dev, &q6usb_dai_component, + q6usb_be_dais, ARRAY_SIZE(q6usb_be_dais)); + snd_soc_usb_set_priv_data(dev, &data->priv); + + return 0; + +detach_device: + iommu_detach_device(data->priv.domain, &pdev->dev); +free_domain: + iommu_domain_free(data->priv.domain); + + return ret; +} + +static int q6usb_dai_dev_remove(struct platform_device *pdev) +{ + struct q6usb_port_data *data = platform_get_drvdata(pdev); + + iommu_detach_device(data->priv.domain, &pdev->dev); + iommu_domain_free(data->priv.domain); + + snd_soc_usb_remove_port(&pdev->dev); + + return 0; +} + +static const struct of_device_id q6usb_dai_device_id[] = { + { .compatible = "qcom,q6usb-dais" }, + {}, +}; +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 = q6usb_dai_dev_remove, +}; +module_platform_driver(q6usb_dai_platform_driver); + +MODULE_DESCRIPTION("Q6 USB backend dai driver"); +MODULE_LICENSE("GPL"); From patchwork Thu Jan 26 03:14:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48468 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69400wrn; Wed, 25 Jan 2023 19:16:35 -0800 (PST) X-Google-Smtp-Source: AMrXdXu8vUGMdRsFEtnzLj8Xi8IQD4qQR5Jhg2rGeTDLMtWfkQOdLi4uDyVrHp3iKZSyV5ig147m X-Received: by 2002:a05:6a20:4c9f:b0:b8:694c:201 with SMTP id fq31-20020a056a204c9f00b000b8694c0201mr35648008pzb.11.1674702994992; Wed, 25 Jan 2023 19:16:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702994; cv=none; d=google.com; s=arc-20160816; b=oyAnidBXGsi+/NK55VDvhg2LyqZ/HJyrWP4uwmNO3Y1u2Kbn2rPgqNGYP7lz5OpIqs rGWdg6NYY6Rv6JKmLS8tTk8fadJDI8QmsMCJ/PV9s2tW53JsbUChYeZV8xaA/fqzitqy W+Fp1dpAtcxEwqfJ2c1P5UmArP/E/tENqyaBaKQUao11sLikPbe0PDpCszw2EP0loUqT +GXs/g14hxbB+uyMFBco6uh/j+asjHrqaAFj5Lbd/oiSxOrMQ0PTQq7r+jAgpMmFFVtq F0nksMKxgsfcrgJQaqtD5KWQvY+aaPXyN8CIdazeLJDFaBeByHcEOi4wYeraTPiZ/fjN bRWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=SiGwMQVfI8qUMo4oBmUYasKXPqJDaQ0HCFvv1Uhc3es=; b=bg3jaoIc9zIfxUqU+tGbkqhCxMI3Eqbp4fF46D/WXROTChzixsakTXchZtvbiIpfc2 UOCVLF8f56fLpUJ3kvXJMPgWoWqdzgThBKKyycm87bE9LD6s4HubzvLG+3ivwQe8pT9M ptrZjcqKC5N2nrtJYgkkWvFLtLRGF9cUQjTLHLZIdua98vPg0wspgV0VnbR7tKYwxyGb yUVNOgf0V2EP/WJv6QlNqK7MfSRdQ7WlZx6vyACJg+cNdBoMWjJ+x9Pfe59poMtuATOl KADzPIufAm+PM70P/85k9gptQ4nmd+4LCZTWQaEx7EVvR7Xox9ggW7n4yL58e8VvkE6S kbOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=j8ZCJAUm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b29-20020a63715d000000b004cc256ee218si6987784pgn.365.2023.01.25.19.16.22; Wed, 25 Jan 2023 19:16:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=j8ZCJAUm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236188AbjAZDP7 (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45932 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236214AbjAZDP5 (ORCPT ); Wed, 25 Jan 2023 22:15:57 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 77B4E6601C; Wed, 25 Jan 2023 19:15:19 -0800 (PST) Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q38Osk022211; Thu, 26 Jan 2023 03:14:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=SiGwMQVfI8qUMo4oBmUYasKXPqJDaQ0HCFvv1Uhc3es=; b=j8ZCJAUmctepwhJKoUCDJ1WHqWaC8eFgIArFFl+ZesONe6rhcRkjtet1ApA/MkX82isa iC4u2GCOzWq/2buZJ0sdKQnUBVtLyahg5Njz355JGPhTNXiFGEv1qPlZWHo2LGPHpKdu pa7j3XdoVZ7OTJpLgKZCSTILNNhf+CB8RHHhgS6584Eu7N4Et2aXMfPFe+5RXREZX0y/ O7ZuJaRFP8UcO8PbP8OMGpCqMWj+61cM1byZfGtKI6ls0zgzpqiCWqZ7HgDR4VnQ7Zyx Rd7NqRMCDlM93n+J8QjlOw1i2h5yBPMs0Kl0nTWO+0gM27E/5gHmDEmYFgIbi9wBODms ww== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb0qrsx77-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:45 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EjBj031324 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:45 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:44 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 12/22] sound: usb: card: Introduce USB SND platform op callbacks Date: Wed, 25 Jan 2023 19:14:14 -0800 Message-ID: <20230126031424.14582-13-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 9vPalcDpYzI_lkkCJI4Ee3kCXXK1r2kB X-Proofpoint-ORIG-GUID: 9vPalcDpYzI_lkkCJI4Ee3kCXXK1r2kB X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=806 malwarescore=0 mlxscore=0 priorityscore=1501 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053367685490790?= X-GMAIL-MSGID: =?utf-8?q?1756053367685490790?= Allow for different platforms to be notified on USB SND connect/disconnect seqeunces. This allows for platform USB SND modules to properly initialize and populate internal structures with references to the USB SND chip device. Signed-off-by: Wesley Cheng --- sound/usb/card.c | 28 ++++++++++++++++++++++++++++ sound/usb/card.h | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index 26268ffb8274..803230343c16 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -117,6 +117,24 @@ MODULE_PARM_DESC(skip_validation, "Skip unit descriptor validation (default: no) static DEFINE_MUTEX(register_mutex); static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; static struct usb_driver usb_audio_driver; +static struct snd_usb_platform_ops *platform_ops; + +int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops) +{ + if (platform_ops) + return -EEXIST; + + platform_ops = ops; + return 0; +} +EXPORT_SYMBOL_GPL(snd_usb_register_platform_ops); + +int snd_usb_unregister_platform_ops(void) +{ + platform_ops = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(snd_usb_unregister_platform_ops); /* * disconnect streams @@ -910,6 +928,10 @@ static int usb_audio_probe(struct usb_interface *intf, usb_set_intfdata(intf, chip); atomic_dec(&chip->active); mutex_unlock(®ister_mutex); + + if (platform_ops->connect_cb) + platform_ops->connect_cb(intf, chip); + return 0; __error: @@ -943,6 +965,9 @@ static void usb_audio_disconnect(struct usb_interface *intf) if (chip == USB_AUDIO_IFACE_UNUSED) return; + if (platform_ops->disconnect_cb) + platform_ops->disconnect_cb(intf); + card = chip->card; mutex_lock(®ister_mutex); @@ -1087,6 +1112,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) chip->system_suspend = chip->num_suspended_intf; } + if (platform_ops->suspend_cb) + platform_ops->suspend_cb(intf, message); + return 0; } diff --git a/sound/usb/card.h b/sound/usb/card.h index 40061550105a..2249c411c3a1 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -206,4 +206,24 @@ struct snd_usb_stream { struct list_head list; }; +struct snd_usb_platform_ops { + void (*connect_cb)(struct usb_interface *intf, struct snd_usb_audio *chip); + void (*disconnect_cb)(struct usb_interface *intf); + void (*suspend_cb)(struct usb_interface *intf, pm_message_t message); +}; + +#if IS_ENABLED(CONFIG_SND_USB_AUDIO) +int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops); +int snd_usb_unregister_platform_ops(void); +#else +int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops) +{ + return -EOPNOTSUPP; +} + +int snd_usb_unregister_platform_ops(void) +{ + return -EOPNOTSUPP; +} +#endif /* IS_ENABLED(CONFIG_SND_USB_AUDIO) */ #endif /* __USBAUDIO_CARD_H */ From patchwork Thu Jan 26 03:14:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48471 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69576wrn; Wed, 25 Jan 2023 19:17:08 -0800 (PST) X-Google-Smtp-Source: AK7set80s6P7U3wlx9SsZnjceC1W7wilPvaBwMDdyyjN6c0rxj+5digDx/YwI5AyQ29ysrm2MBKJ X-Received: by 2002:a05:6a00:1a87:b0:590:6ff5:5713 with SMTP id e7-20020a056a001a8700b005906ff55713mr3500759pfv.9.1674703028016; Wed, 25 Jan 2023 19:17:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703028; cv=none; d=google.com; s=arc-20160816; b=qm3+sF+pC6v+HOq9JckGrX/z4Vi8yApyR7T2VlW7tRb+7azkZtaHGyJ3hco7WuLTs+ 0YDVjzst/tSwjQcQn9ZUY1RaBz2DM8ytN4DNRGYg3BnmpcnVXGyKBEQMu8NekRoxY/en G7WB2xhFPGXWZbErMHkDzehgB+MVgClaxtIAdoZiKIzfCI6jcXNmmXpFyAls8nhH0/ei q72uSMlXVDRpW3ZLdjglowaYepiRYJ3ZR0M13zCS2pF17RSwJ3cZdZ+SuJfv8qmOd6NF NwfI9re1dPLDbqlJMipse/G6VZKDhp97timZ/yOjjY7fKN78TlqPggT+u47jUyy/zCOz Rl7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=9DUsAREdcbyKkri9QQ9DarmPLi+PaOWxom+nSMkrqB4=; b=n+VLz3ETuevQD85KVt3mRnjBnMDSriHb/GlZHB6AoiaDXy0udojRwl8CGJB+49BOS7 ZRoJJvqr1WAuZGIafP319WkeJfCNcG6FB6zxkEn1D7pF2rL68Nzw0YPf8s0oEASunxAR OOmKKISMvVd8uesSnlHfjwsB5FEDBcWTcArdxTJE/UzNPvaylCaQQ4W0Q/0FNL08SuOp 1Mg6TSBGG2XBmSD+N/tIpVZf5Kyrjj9nsBcbmAotnKiWAtdc9gjNKTwNU4RCEllLc3AO Fq+nZdSqUbsUcPW+9YvByK/3sk4J6k7MspdQ9zl1fLfPfXJDlpDilunUrD6LZgiG33UF aNzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=l6bxJjql; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ds10-20020a056a004aca00b005766cd2128dsi6934338pfb.269.2023.01.25.19.16.56; Wed, 25 Jan 2023 19:17:07 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=l6bxJjql; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236304AbjAZDQV (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236206AbjAZDQM (ORCPT ); Wed, 25 Jan 2023 22:16:12 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BBF1565F02; Wed, 25 Jan 2023 19:15:43 -0800 (PST) Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q2va2R018786; Thu, 26 Jan 2023 03:14:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=9DUsAREdcbyKkri9QQ9DarmPLi+PaOWxom+nSMkrqB4=; b=l6bxJjql0QVnu4oIc6epvCpUIO4hW0Fkzmso0X4dnD83PcPLMT5iJehMQmOgoWp+sYYv 3x9BFugKqbEY75ymXTYpZ9wjVjAhJQGtqUh6CxEot7gs2IsoV0F1lk30g/AwU5bpofyw eAAEjKIoJqFzn2c78bKdONCNDCuL+mFD0U8mww9+YojFlNibwwy4mKT6c/GXSQqC6Ukn wGE5zGjJzoJgY1DwF3iNf4DAT2DlwgPCYePFiOIz4U7ki6W+CcJypUIxqr7L6RFHYLCW LzpWLduYZUkIVJT3CGQztQsPiIA/dSLjiOlkmKkfbGNBKnz+rxwCMrRSBUSlHBNP1BK2 xQ== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nbd7arbm7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:46 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EjRY011805 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:45 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:45 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 13/22] sound: usb: Export USB SND APIs for modules Date: Wed, 25 Jan 2023 19:14:15 -0800 Message-ID: <20230126031424.14582-14-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: iRx374J8JRqYXE32goI7hpBI2-vZkO0- X-Proofpoint-GUID: iRx374J8JRqYXE32goI7hpBI2-vZkO0- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 impostorscore=0 adultscore=0 clxscore=1015 priorityscore=1501 phishscore=0 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053402377139424?= X-GMAIL-MSGID: =?utf-8?q?1756053402377139424?= Some vendor modules will utilize useful parsing and endpoint management APIs to start audio playback/capture. Signed-off-by: Wesley Cheng --- include/sound/pcm_params.h | 4 +++ sound/core/oss/pcm_oss.c | 58 ---------------------------------- sound/core/pcm_lib.c | 65 ++++++++++++++++++++++++++++++++++++++ sound/usb/card.c | 2 ++ sound/usb/endpoint.c | 2 ++ sound/usb/helper.c | 1 + sound/usb/pcm.c | 9 ++++-- sound/usb/pcm.h | 12 +++++++ 8 files changed, 92 insertions(+), 61 deletions(-) diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index ba184f49f7e1..407557b72700 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -17,6 +17,10 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, snd_pcm_hw_param_t var, int *dir); int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, int *dir); +int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir); +int snd_interval_refine_set(struct snd_interval *i, unsigned int val); #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index ac2efeb63a39..eb45e37bb875 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -103,16 +103,6 @@ static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int return changed; } -static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) -{ - struct snd_interval t; - t.empty = 0; - t.min = t.max = val; - t.openmin = t.openmax = 0; - t.integer = 1; - return snd_interval_refine(i, &t); -} - /** * snd_pcm_hw_param_value_min * @params: the hw_params instance @@ -443,54 +433,6 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, return v; } -static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed; - if (hw_is_mask(var)) { - struct snd_mask *m = hw_param_mask(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_mask_none(m); - } else { - if (dir > 0) - val++; - else if (dir < 0) - val--; - changed = snd_mask_refine_set(hw_param_mask(params, var), val); - } - } else if (hw_is_interval(var)) { - struct snd_interval *i = hw_param_interval(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_interval_none(i); - } else if (dir == 0) - changed = snd_interval_refine_set(i, val); - else { - struct snd_interval t; - t.openmin = 1; - t.openmax = 1; - t.empty = 0; - t.integer = 0; - if (dir < 0) { - t.min = val - 1; - t.max = val; - } else { - t.min = val; - t.max = val+1; - } - changed = snd_interval_refine(i, &t); - } - } else - return -EINVAL; - if (changed > 0) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - /** * snd_pcm_hw_param_set * @pcm: PCM instance diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 8b6aeb8a78f7..8305fd0860ad 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -2532,3 +2532,68 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, return 0; } EXPORT_SYMBOL_GPL(snd_pcm_add_chmap_ctls); + +int snd_interval_refine_set(struct snd_interval *i, unsigned int val) +{ + struct snd_interval t; + + t.empty = 0; + t.min = t.max = val; + t.openmin = t.openmax = 0; + t.integer = 1; + return snd_interval_refine(i, &t); +} +EXPORT_SYMBOL_GPL(snd_interval_refine_set); + +int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, unsigned int val, + int dir) +{ + int changed; + + if (hw_is_mask(var)) { + struct snd_mask *m = hw_param_mask(params, var); + + if (val == 0 && dir < 0) { + changed = -EINVAL; + snd_mask_none(m); + } else { + if (dir > 0) + val++; + else if (dir < 0) + val--; + changed = snd_mask_refine_set(hw_param_mask(params, var), val); + } + } else if (hw_is_interval(var)) { + struct snd_interval *i = hw_param_interval(params, var); + + if (val == 0 && dir < 0) { + changed = -EINVAL; + snd_interval_none(i); + } else if (dir == 0) + changed = snd_interval_refine_set(i, val); + else { + struct snd_interval t; + + t.openmin = 1; + t.openmax = 1; + t.empty = 0; + t.integer = 0; + if (dir < 0) { + t.min = val - 1; + t.max = val; + } else { + t.min = val; + t.max = val+1; + } + changed = snd_interval_refine(i, &t); + } + } else + return -EINVAL; + if (changed > 0) { + params->cmask |= 1 << var; + params->rmask |= 1 << var; + } + return changed; +} +EXPORT_SYMBOL_GPL(_snd_pcm_hw_param_set); diff --git a/sound/usb/card.c b/sound/usb/card.c index 803230343c16..59be5f543315 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -1071,6 +1071,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) } return 0; } +EXPORT_SYMBOL_GPL(snd_usb_autoresume); void snd_usb_autosuspend(struct snd_usb_audio *chip) { @@ -1084,6 +1085,7 @@ void snd_usb_autosuspend(struct snd_usb_audio *chip) for (i = 0; i < chip->num_interfaces; i++) usb_autopm_put_interface(chip->intf[i]); } +EXPORT_SYMBOL_GPL(snd_usb_autosuspend); static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) { diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 310cd6fb0038..25b79c067956 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -858,6 +858,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, mutex_unlock(&chip->mutex); return ep; } +EXPORT_SYMBOL_GPL(snd_usb_endpoint_open); /* * snd_usb_endpoint_set_sync: Link data and sync endpoints @@ -1506,6 +1507,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, mutex_unlock(&chip->mutex); return err; } +EXPORT_SYMBOL_GPL(snd_usb_endpoint_prepare); /* get the current rate set to the given clock by any endpoint */ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock) diff --git a/sound/usb/helper.c b/sound/usb/helper.c index a4410267bf70..b4ed9ef3eeb3 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -62,6 +62,7 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype } return NULL; } +EXPORT_SYMBOL_GPL(snd_usb_find_csint_desc); /* * Wrapper for usb_control_msg(). diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8ed165f036a0..0b01a5dfcb73 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -87,7 +87,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream /* * find a matching audio format */ -static const struct audioformat * +const struct audioformat * find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, unsigned int rate, unsigned int channels, bool strict_match, struct snd_usb_substream *subs) @@ -147,8 +147,9 @@ find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, } return found; } +EXPORT_SYMBOL_GPL(find_format); -static const struct audioformat * +const struct audioformat * find_substream_format(struct snd_usb_substream *subs, const struct snd_pcm_hw_params *params) { @@ -156,6 +157,7 @@ find_substream_format(struct snd_usb_substream *subs, params_rate(params), params_channels(params), true, subs); } +EXPORT_SYMBOL_GPL(find_substream_format); static int init_pitch_v1(struct snd_usb_audio *chip, int ep) { @@ -418,7 +420,7 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as) return 0; } -static void close_endpoints(struct snd_usb_audio *chip, +void close_endpoints(struct snd_usb_audio *chip, struct snd_usb_substream *subs) { if (subs->data_endpoint) { @@ -432,6 +434,7 @@ static void close_endpoints(struct snd_usb_audio *chip, subs->sync_endpoint = NULL; } } +EXPORT_SYMBOL(close_endpoints); /* * hw_params callback diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 493a4e34d78d..43a4a03dfce7 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -13,4 +13,16 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, struct audioformat *fmt); +void close_endpoints(struct snd_usb_audio *chip, + struct snd_usb_substream *subs); +int configure_endpoints(struct snd_usb_audio *chip, + struct snd_usb_substream *subs); + +const struct audioformat * +find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, + unsigned int rate, unsigned int channels, bool strict_match, + struct snd_usb_substream *subs); +const struct audioformat * +find_substream_format(struct snd_usb_substream *subs, + const struct snd_pcm_hw_params *params); #endif /* __USBAUDIO_PCM_H */ From patchwork Thu Jan 26 03:14:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48474 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69667wrn; Wed, 25 Jan 2023 19:17:25 -0800 (PST) X-Google-Smtp-Source: AK7set+zXOEZUrRe+HmUiJu+hbHL6S5sMCZ4ZX7Mx+j/x0ZNpkl6NytcjV2E5gY/ZUbaHLIEcHLX X-Received: by 2002:a05:6a20:9f8e:b0:bb:ccef:f894 with SMTP id mm14-20020a056a209f8e00b000bbcceff894mr3977702pzb.38.1674703045529; Wed, 25 Jan 2023 19:17:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703045; cv=none; d=google.com; s=arc-20160816; b=UUmD8uwMykIHaXZkaRrk72Iwmv6tUrMmmc+gde/UEkmMZgk2xz//EPlPDj5ArzmqPu OHwEEHEO4onSKfgGQupU2pvO8H26wIBXGYuP4O3STM4h8rsdXVYwrB1Umj2vTRzFgWg3 KNvwwRIRECtS1o9E+sbsiao7Ci4LR4m4wDKnkgFNpESuolHAK+IQ99LYB7LZaodtZRa2 oiRQiRStzsPcH7d/Nv1pYkTlDxpMCvXV5Fjo9hnYVF2eZdY79I2CelKnxSRr/FPFbDKW WgYIhEv/7fzEpLrX9B/2Gv+j8ckv/V6kiKD2Y846DS0JBhazpcQfKN/YQCRCAElnUMM9 AEOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=PH3gtljA+8WTPQ8qZ6OJp1NsrMGDODJi5wV18FONxF4=; b=YTl1RWIEhdloJztC1nJu9syBoZIa3txM56FeL4zsD9wDPV7lD697Z1ooQzeYMnnMw+ KhN5p84WFwrtOHonVW8waJao9iucvwaYi6VaJkDU/dHjt0rDRKi4Sind4+idP0oW1wsY 7DJGszuHkuqKyYEZzdgmFXtGFUVhV9Eb+UBiR5ssD/Ee9vjn20X+udT7FoUIrMc0XqBx k+YPtIGV4jN+zGxmOm3WTV9IWmJd0XlkhTYc/hLqjdDdWvMV+OJlWWtzVWq0pCSg8TX2 /xK3jRZj7mfDHOF3OTAO9mSrM3+pBpEHQrKvB2b+4LkijtIqz0RK+dLTJYNS7sU2IstO 9GSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=QNOT3ILF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o27-20020a63921b000000b004788c847617si7448585pgd.292.2023.01.25.19.17.13; Wed, 25 Jan 2023 19:17:25 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=QNOT3ILF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235965AbjAZDQH (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236278AbjAZDP7 (ORCPT ); Wed, 25 Jan 2023 22:15:59 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7BD816600F; Wed, 25 Jan 2023 19:15:30 -0800 (PST) Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q3AOrC029160; Thu, 26 Jan 2023 03:14:47 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=PH3gtljA+8WTPQ8qZ6OJp1NsrMGDODJi5wV18FONxF4=; b=QNOT3ILFRta/QlJutJXLvo60iPm0SghufVXoQ5fGdekuaY8ZX1mfEhoVLOcXa9Cxce3l cK+nNhogdwKhntAJd7IPN3g1vuKs/40tgTLzquwTCxix0DdGg1AH6uRn//BmFmLlc58U plioxS1CjrceUq3Sw5YHSYeB8JdgfJXELWdbSMhND3RNU6TwRGPzJC2RtIS0k0idaBAM F6jnPQFlzuZDnnTQlGZgeQBKIP9RxxZ/B6ilbZ5sIaumhIDyz1V2MbQe3Ne6Oqw0zCxV O34G0De7OIVuqnTSJLfCMhM8JY0wED9a8i6bet8qXvocl6yt4BwYWKNYzL/2RP7/pQph iA== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb0qrsx78-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:47 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EkhV031336 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:46 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:45 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 14/22] dt-bindings: usb: dwc3: Add snps,num-hc-interrupters definition Date: Wed, 25 Jan 2023 19:14:16 -0800 Message-ID: <20230126031424.14582-15-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: hDAZbe1hPP_j9IKYfJbKnW_JHqqjuvNa X-Proofpoint-ORIG-GUID: hDAZbe1hPP_j9IKYfJbKnW_JHqqjuvNa X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=541 malwarescore=0 mlxscore=0 priorityscore=1501 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053420625136613?= X-GMAIL-MSGID: =?utf-8?q?1756053420625136613?= Add a new definition for specifying how many XHCI secondary interrupters can be allocated. XHCI in general can potentially support up to 1024 interrupters, which some uses may want to limit depending on how many users utilize the interrupters. Signed-off-by: Wesley Cheng --- Documentation/devicetree/bindings/usb/snps,dwc3.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml index 6d78048c4613..4faaec9655e0 100644 --- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml @@ -349,6 +349,18 @@ properties: items: enum: [1, 4, 8, 16, 32, 64, 128, 256] + snps,num-hc-interrupters: + description: + Defines the maximum number of XHCI host controller interrupters that can + be supported. The XHCI host controller has support to allocate multiple + event rings, which can be assigned to different clients/users. The DWC3 + controller has a maximum of 8 interrupters. If this is not defined then + the value will be defaulted to 1. This parameter is used only when + operating in host mode. + $ref: /schemas/types.yaml#/definitions/uint8 + minimum: 1 + maximum: 8 + port: $ref: /schemas/graph.yaml#/properties/port description: From patchwork Thu Jan 26 03:14:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48472 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69638wrn; Wed, 25 Jan 2023 19:17:18 -0800 (PST) X-Google-Smtp-Source: AK7set/qB6rwBAD+ZYMwZLdpnG/bmEDfpyJL+ZDrf85tBF4qurmuJvErm9xzoDMAfDEasjUHrFrE X-Received: by 2002:a17:903:11c8:b0:196:2e92:e546 with SMTP id q8-20020a17090311c800b001962e92e546mr4097086plh.44.1674703038195; Wed, 25 Jan 2023 19:17:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703038; cv=none; d=google.com; s=arc-20160816; b=Z86xN2vrcYizXOg/9q/dwuV6l4gWU0ljxLMHP/KV0ExHMWGC7PenwbVX8lXJBocuDZ zthb87C1RbJKJSch8z6SHhg1LRYu+eZKufoNTBaeH7IU2+n1LbffapUu62cVzUGa3XPT NmC9W3ziRilZOZDpz2QGD83QeSeiimGD5V6LNdrTaCpfxL1Wq2B4WRtdKPpWAVReqd1R fr9Mp+3+wLmp4zrAiSZkeqbyFyn7eqjYz1e+zGEucaCA4Bg12oCJlwB/yitEstnv+hHR 6Xsf4dElnusN3BnlNs37ZW1Vkewlkc6IO8jCDZCj/mpPHc9gS6lSxBrB91naO0nqhVxS GWDw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=X5M6sUavZ3fUTxE7UWPbNLuT6/8dgX69k0uiiidcChY=; b=0g2Fnx9KGqTKAN0mb4RLjOHfWSKnB5zOpnJaxPUvKXbbmDTq3aSP/YKOxjwq8VMUTi w2+9iDdeyvuqrDL5+ZHMxRL+Y34GOU7CzEdMGFeBuuuv+fGBVXz5ywTIzbZanbYlBEdK fjOUzb7eeF4ZgCTu7Bw983klthexuN/qVwooEp5THLTYw2TN0m18HEAS49I4Mj3copKs GW+Hb8KvlVL/OwFH1QC8ONnfnLdhfMwm+kDzOVA4/xwe+eEsMqWa8Ye2PCGIVvpHD6Ql zwDydX03htYt0mnkAjL7kRLwtP4GR9W5WoIFq9530/QFZBjFF53YTn/J1ZGEaic1mj4b DY2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b="llnqE/Pu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n1-20020a170902e54100b00189aab9cdbcsi223025plf.605.2023.01.25.19.17.06; Wed, 25 Jan 2023 19:17:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b="llnqE/Pu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236321AbjAZDQR (ORCPT + 99 others); Wed, 25 Jan 2023 22:16:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236266AbjAZDQL (ORCPT ); Wed, 25 Jan 2023 22:16:11 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E24365F0C; Wed, 25 Jan 2023 19:15:42 -0800 (PST) Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q3EmGS017428; Thu, 26 Jan 2023 03:14:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=X5M6sUavZ3fUTxE7UWPbNLuT6/8dgX69k0uiiidcChY=; b=llnqE/Pu+nfIT9sEy0Y9PkamSTRCfgd7b2VpquznVHcSUgTjLG4LfVBhKUSf+zYgjzOb dI25SPmMp4ArPx03qfNKoqT8Y4eqf6GqwkiEV9ZZJPVyzOSmKELc3klzi1XWGUd/KBo3 YawrZCb9IQ66oRnUq9ehUrRyLyzALWivXz27EtQStRxuYI59JhQ84+qLUJu+KVLgtYKr 3lYnlwHmvSLMeZmeNhiklZ6GFrxoD04q/WEmSZfIu+6+oznMUPnLhXGedBiTYkYarNcF JCpxWLB9kP5nL6ynwndmplR7nwm+/TTQlw7m5YOn0hL88W/tVppvDXKMkT5UVO1W/zD0 fw== Received: from nasanppmta05.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb2nssqw1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:47 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA05.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3ElLH016126 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:47 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:46 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 15/22] usb: dwc3: Add DT parameter to specify maximum number of interrupters Date: Wed, 25 Jan 2023 19:14:17 -0800 Message-ID: <20230126031424.14582-16-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: Iz1hvovHMkS4yg2EnzbrH7ZRdk2gOWvv X-Proofpoint-GUID: Iz1hvovHMkS4yg2EnzbrH7ZRdk2gOWvv X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 mlxlogscore=621 spamscore=0 malwarescore=0 impostorscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 mlxscore=0 adultscore=0 phishscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053412901072804?= X-GMAIL-MSGID: =?utf-8?q?1756053412901072804?= Allow for the DWC3 host driver to pass along a 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. Signed-off-by: Wesley Cheng --- drivers/usb/dwc3/core.c | 12 ++++++++++++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/host.c | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 476b63618511..67d6f0ae81d2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1446,6 +1446,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; + u8 num_hc_interrupters; const char *usb_psy_name; int ret; @@ -1468,6 +1469,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); @@ -1511,6 +1515,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_u8(dev, "snps,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) @@ -1589,6 +1599,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 8f9959ba9fd4..09037299da53 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1050,6 +1050,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 @@ -1275,6 +1276,7 @@ struct dwc3 { u8 tx_max_burst_prd; u8 tx_fifo_resize_max_num; u8 clear_stall_protocol; + u8 num_hc_interrupters; const char *hsphy_interface; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index f6f13e7f1ba1..52a284fdd704 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -66,7 +66,7 @@ static int dwc3_host_get_irq(struct dwc3 *dwc) int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[4]; + struct property_entry props[5]; struct platform_device *xhci; int ret, irq; int prop_idx = 0; @@ -112,6 +112,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_U8("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 26 03:14:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48478 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp72228wrn; Wed, 25 Jan 2023 19:26:17 -0800 (PST) X-Google-Smtp-Source: AK7set8bh1tPXnUhJRwGdctCx8toS1coGkvhiJZ/cu3CZk5FYY6ad1hHONCERKFHgSUG2VENp8RD X-Received: by 2002:a17:90b:4b10:b0:229:91f7:8476 with SMTP id lx16-20020a17090b4b1000b0022991f78476mr625119pjb.10.1674703576728; Wed, 25 Jan 2023 19:26:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703576; cv=none; d=google.com; s=arc-20160816; b=c0FnV9jr9LG6OtqZ+HIUSdY1/MwO6NJy9qQOP93yGUqZ72ANmevGtCFc2FjKVvukvg E2juC1BSQeJvTbNlJK0FophqUqMj+DpZBAZQm1YRWSk28Lhr3zlwdgLbV+M0GC48WDZ0 Esga415mYZcu0XoMQynkpn3qeXmyjwL1jCEzAu6usoIegTaS0DnNIVXWNf9XGtv74HE1 KF5FATjAKJ2deAzzoRWDiFIGNluls0Vkqt2ZVcI2Mgpt/XF45bBuMQiaJzsA2y768+uo bffFpTVPgNvPbLwgr+UahTbyvvVTaZQvaJ56AGtAdU0ivKk21oKxCA4NoCCRYs3j3f+r ndWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Mkm2O7W+v5timDUM+9z8KlTFvuk0CA/1cSxQdJg+F20=; b=hJoxiOSvcEfy4B+iSayd7hIJLkfDzemEZrh1bwly234esoxSLBWtdrd+LQoGuqM9I7 qhE+ouuxzvDyut21nTRvFN3Bnnis2tQ5CGO5aqoHbzyUN4TvL/T28e5ZqRK0qRg/0e0d xGNU75HaOkAktzkH+KJzRXCNMsIHBch+38gU3/wr9xRhpvbyX+RVhIJyhLrb9qqFccbU V9D2IXbuMiDyJBIzvz61TtOqj69OLj5Kk4RzG/V8FxX3lDB5aOvaA0QnHNtWPdpyH66M A2yAumcgfXiwd5oIvuOJbzP5v1zDJNOowz2h5uacAn1FeG0ERD5Xc+lP0F/VJXwqmXSR qjeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Nz9819HC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o13-20020a17090a420d00b002298cb34320si309356pjg.116.2023.01.25.19.26.04; Wed, 25 Jan 2023 19:26:16 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Nz9819HC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230233AbjAZDVy (ORCPT + 99 others); Wed, 25 Jan 2023 22:21:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235766AbjAZDVu (ORCPT ); Wed, 25 Jan 2023 22:21:50 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A517C66ECA; Wed, 25 Jan 2023 19:21:18 -0800 (PST) Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q38BHh017806; Thu, 26 Jan 2023 03:14:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=Mkm2O7W+v5timDUM+9z8KlTFvuk0CA/1cSxQdJg+F20=; b=Nz9819HCvKmB3XvO1kkO5SB6/QCBDpXPgP/w04CivgNq+dsWSIlyJM9H4wxajAP2e4Fe 478SOWTzKGQZDfqVA4tUgeiBqsLDYakfTFnO4Z94ryhkaltYtbZuEOv65fAcu0LJTPqW KaSo90PaqlR29IFlOHnUEQHDXyggOM4h8Gug4TCvxwaM6j56610DIyOzehx6lN2kf2pO qQ/SjTKgs3b1Uc8Prf9DeG/xqvw1Mca8TBAdQ/3LRHhM6TtoVbNwpZPI7GfkuNTh76MS eNzQpfpKl6MAjiHur3lq6dvE8JMHgJQzqEUS9910t8zYt3Buzhlnq5bA9OzUhqR5euYD fw== Received: from nasanppmta01.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nb6jc9bs1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:48 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3ElDM008323 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:47 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:47 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 16/22] sound: usb: Introduce QC USB SND offloading support Date: Wed, 25 Jan 2023 19:14:18 -0800 Message-ID: <20230126031424.14582-17-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: 9htL2P6yek8cy5EfqwJqzRaC6XLQlJ2x X-Proofpoint-GUID: 9htL2P6yek8cy5EfqwJqzRaC6XLQlJ2x X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 phishscore=0 impostorscore=0 adultscore=0 priorityscore=1501 bulkscore=0 suspectscore=0 clxscore=1015 mlxscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053977784010629?= X-GMAIL-MSGID: =?utf-8?q?1756053977784010629?= Several Qualcomm SoCs have a dedicated audio DSP, which has the ability to support USB sound devices. This vendor driver will implement the required handshaking with the DSP, in order to pass along required resources that will be utilized by the DSP's USB SW. The communication channel used for this handshaking will be using the QMI protocol. Required resources include: - Allocated secondary event ring address - EP transfer ring address - Interrupter number The above information will allow for the audio DSP to execute USB transfers over the USB bus. It will also be able to support devices that have an implicit feedback and sync endpoint as well. Offloading these data transfers will allow the main/applications processor to enter lower CPU power modes, and sustain a longer duration in those modes. Audio offloading is initiated with the following sequence: 1. Userspace configures to route audio playback to USB backend and starts playback on the platform soundcard. 2. The Q6DSP AFE will communicate to the audio DSP to start the USB AFE port. 3. This results in a QMI packet with a STREAM enable command. 4. The QC audio offload driver will fetch the required resources, and pass this information as part of the QMI response to the STREAM enable command. 5. Once the QMI response is received the audio DSP will start queuing data on the USB bus. Signed-off-by: Wesley Cheng --- sound/usb/Kconfig | 14 + sound/usb/Makefile | 2 +- sound/usb/qcom/Makefile | 2 + sound/usb/qcom/qc_audio_offload.c | 1775 ++++++++++++++++++++++++++++ sound/usb/qcom/usb_audio_qmi_v01.c | 892 ++++++++++++++ sound/usb/qcom/usb_audio_qmi_v01.h | 162 +++ 6 files changed, 2846 insertions(+), 1 deletion(-) create mode 100644 sound/usb/qcom/Makefile create mode 100644 sound/usb/qcom/qc_audio_offload.c 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/Kconfig b/sound/usb/Kconfig index 059242f15d75..18d65a0d905a 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -165,6 +165,20 @@ config SND_BCD2000 To compile this driver as a module, choose M here: the module will be called snd-bcd2000. +config QC_USB_AUDIO_OFFLOAD + tristate "Qualcomm Audio Offload driver" + select SND_PCM + help + Say Y here to enable the Qualcomm USB audio offloading feature + + This module sets up the required QMI stream enable/disable + responses to requests generated by the audio DSP. It passes the + USB transfer resource references, so that the audio DSP can issue + USB transfers to the host controller. + + To compile this driver as a module, choose M here: the module + will be called qc-audio-offload. + source "sound/usb/line6/Kconfig" endif # SND_USB diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 9ccb21a4ff8a..2243ae333ec9 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -33,5 +33,5 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o -obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ +obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ qcom/ obj-$(CONFIG_SND_USB_LINE6) += line6/ diff --git a/sound/usb/qcom/Makefile b/sound/usb/qcom/Makefile new file mode 100644 index 000000000000..d27d39beb8ce --- /dev/null +++ b/sound/usb/qcom/Makefile @@ -0,0 +1,2 @@ +snd-usb-audio-qmi-objs := usb_audio_qmi_v01.o qc_audio_offload.o +obj-$(CONFIG_QC_USB_AUDIO_OFFLOAD) += snd-usb-audio-qmi.o \ No newline at end of file diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c new file mode 100644 index 000000000000..c1254d5f680d --- /dev/null +++ b/sound/usb/qcom/qc_audio_offload.c @@ -0,0 +1,1775 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../usbaudio.h" +#include "../card.h" +#include "../midi.h" +#include "../mixer.h" +#include "../proc.h" +#include "../quirks.h" +#include "../endpoint.h" +#include "../helper.h" +#include "../pcm.h" +#include "../format.h" +#include "../power.h" +#include "../stream.h" +#include "../media.h" +#include "usb_audio_qmi_v01.h" + +/* Stream disable request timeout during USB device disconnect */ +#define DEV_RELEASE_WAIT_TIMEOUT 10000 /* in ms */ + +/* Data interval calculation parameters */ +#define BUS_INTERVAL_FULL_SPEED 1000 /* in us */ +#define BUS_INTERVAL_HIGHSPEED_AND_ABOVE 125 /* in us */ +#define MAX_BINTERVAL_ISOC_EP 16 + +#define SND_PCM_CARD_NUM_MASK 0xffff0000 +#define SND_PCM_DEV_NUM_MASK 0xff00 +#define SND_PCM_STREAM_DIRECTION 0xff + +/* iommu resource parameters and management */ +#define PREPEND_SID_TO_IOVA(iova, sid) ((u64)(((u64)(iova)) | \ + (((u64)sid) << 32))) +#define IOVA_BASE 0x1000 +#define IOVA_XFER_RING_BASE (IOVA_BASE + PAGE_SIZE * (SNDRV_CARDS + 1)) +#define IOVA_XFER_BUF_BASE (IOVA_XFER_RING_BASE + PAGE_SIZE * SNDRV_CARDS * 32) +#define IOVA_XFER_RING_MAX (IOVA_XFER_BUF_BASE - PAGE_SIZE) +#define IOVA_XFER_BUF_MAX (0xfffff000 - PAGE_SIZE) + +#define MAX_XFER_BUFF_LEN (24 * PAGE_SIZE) + +struct iova_info { + struct list_head list; + unsigned long start_iova; + size_t size; + bool in_use; +}; + +struct intf_info { + unsigned long data_xfer_ring_va; + size_t data_xfer_ring_size; + unsigned long sync_xfer_ring_va; + size_t sync_xfer_ring_size; + unsigned long xfer_buf_va; + size_t xfer_buf_size; + phys_addr_t xfer_buf_pa; + unsigned int data_ep_pipe; + unsigned int sync_ep_pipe; + u8 *xfer_buf; + u8 intf_num; + u8 pcm_card_num; + u8 pcm_dev_num; + u8 direction; + bool in_use; +}; + +struct uaudio_qmi_dev { + struct device *dev; + u32 sid; + u32 intr_num; + struct xhci_interrupter *ir; + struct xhci_ring *sec_ring; + struct iommu_domain *domain; + + /* list to keep track of available iova */ + struct list_head xfer_ring_list; + size_t xfer_ring_iova_size; + unsigned long curr_xfer_ring_iova; + struct list_head xfer_buf_list; + size_t xfer_buf_iova_size; + unsigned long curr_xfer_buf_iova; + + /* bit fields representing pcm card enabled */ + unsigned long card_slot; + /* indicate event ring mapped or not */ + bool er_mapped; + /* reference count to number of possible consumers */ + atomic_t qdev_in_use; + /* idx to last udev card number plugged in */ + unsigned int last_card_num; +}; + +struct uaudio_dev { + struct usb_device *udev; + /* audio control interface */ + struct usb_host_interface *ctrl_intf; + unsigned int card_num; + unsigned int usb_core_id; + atomic_t in_use; + struct kref kref; + wait_queue_head_t disconnect_wq; + + /* interface specific */ + int num_intf; + struct intf_info *info; + struct snd_usb_audio *chip; +}; + +static struct uaudio_dev uadev[SNDRV_CARDS]; +static struct uaudio_qmi_dev *uaudio_qdev; +static struct uaudio_qmi_svc *uaudio_svc; +static DEFINE_MUTEX(qdev_mutex); + +struct uaudio_qmi_svc { + struct qmi_handle *uaudio_svc_hdl; + struct work_struct qmi_disconnect_work; + struct workqueue_struct *uaudio_wq; + struct sockaddr_qrtr client_sq; + bool client_connected; +}; + +enum mem_type { + MEM_EVENT_RING, + MEM_XFER_RING, + MEM_XFER_BUF, +}; + +/* Supported audio formats */ +enum usb_qmi_audio_format { + USB_QMI_PCM_FORMAT_S8 = 0, + USB_QMI_PCM_FORMAT_U8, + USB_QMI_PCM_FORMAT_S16_LE, + USB_QMI_PCM_FORMAT_S16_BE, + USB_QMI_PCM_FORMAT_U16_LE, + USB_QMI_PCM_FORMAT_U16_BE, + USB_QMI_PCM_FORMAT_S24_LE, + USB_QMI_PCM_FORMAT_S24_BE, + USB_QMI_PCM_FORMAT_U24_LE, + USB_QMI_PCM_FORMAT_U24_BE, + USB_QMI_PCM_FORMAT_S24_3LE, + USB_QMI_PCM_FORMAT_S24_3BE, + USB_QMI_PCM_FORMAT_U24_3LE, + USB_QMI_PCM_FORMAT_U24_3BE, + USB_QMI_PCM_FORMAT_S32_LE, + USB_QMI_PCM_FORMAT_S32_BE, + USB_QMI_PCM_FORMAT_U32_LE, + USB_QMI_PCM_FORMAT_U32_BE, +}; + +static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va, + size_t iova_size, size_t mapped_iova_size); +static void uaudio_dev_cleanup(struct uaudio_dev *dev); +static void disable_audio_stream(struct snd_usb_substream *subs); +static struct snd_usb_substream *find_substream(unsigned int card_num, + unsigned int pcm_idx, unsigned int direction); + +/* QMI service disconnect handlers */ +static void qmi_disconnect_work(struct work_struct *w) +{ + struct intf_info *info; + int idx, if_idx; + struct snd_usb_substream *subs; + struct snd_usb_audio *chip; + + /* find all active intf for set alt 0 and cleanup usb audio dev */ + for (idx = 0; idx < SNDRV_CARDS; idx++) { + if (!atomic_read(&uadev[idx].in_use)) + continue; + + chip = uadev[idx].chip; + for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) { + if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use) + continue; + info = &uadev[idx].info[if_idx]; + subs = find_substream(info->pcm_card_num, + info->pcm_dev_num, + info->direction); + if (!subs || !chip || atomic_read(&chip->shutdown)) { + dev_err(&subs->dev->dev, + "no sub for c#%u dev#%u dir%u\n", + info->pcm_card_num, + info->pcm_dev_num, + info->direction); + continue; + } + disable_audio_stream(subs); + } + atomic_set(&uadev[idx].in_use, 0); + mutex_lock(&chip->mutex); + uaudio_dev_cleanup(&uadev[idx]); + mutex_unlock(&chip->mutex); + } +} + +/** + * qmi_bye_cb() - qmi bye message callback + * @handle: QMI handle + * @node: id of the dying node + * + * This callback is invoked when the QMI bye control message is received + * from the QMI client. Handle the message accordingly by ensuring that + * the USB offload path is disabled and cleaned up. At this point, ADSP + * is not utilizing the USB bus. + * + */ +static void qmi_bye_cb(struct qmi_handle *handle, unsigned int node) +{ + struct uaudio_qmi_svc *svc = uaudio_svc; + + if (svc->uaudio_svc_hdl != handle) + return; + + if (svc->client_connected && svc->client_sq.sq_node == node) { + queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work); + svc->client_sq.sq_node = 0; + svc->client_sq.sq_port = 0; + svc->client_sq.sq_family = 0; + svc->client_connected = false; + } +} + +/** + * qmi_svc_disconnect_cb() - qmi client disconnected + * @handle: QMI handle + * @node: id of the dying node + * @port: port of the dying client + * + * Invoked when the remote QMI client is disconnected. Handle this event + * the same way as when the QMI bye message is received. This will ensure + * the USB offloading path is disabled and cleaned up. + * + */ +static void qmi_svc_disconnect_cb(struct qmi_handle *handle, + unsigned int node, unsigned int port) +{ + struct uaudio_qmi_svc *svc; + + if (uaudio_svc == NULL) + return; + + svc = uaudio_svc; + if (svc->uaudio_svc_hdl != handle) + return; + + if (svc->client_connected && svc->client_sq.sq_node == node && + svc->client_sq.sq_port == port) { + queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work); + svc->client_sq.sq_node = 0; + svc->client_sq.sq_port = 0; + svc->client_sq.sq_family = 0; + svc->client_connected = false; + } +} + +/* QMI client callback handlers from QMI interface */ +static struct qmi_ops uaudio_svc_ops_options = { + .bye = qmi_bye_cb, + .del_client = qmi_svc_disconnect_cb, +}; + +static enum usb_audio_device_speed_enum_v01 +get_speed_info(enum usb_device_speed udev_speed) +{ + switch (udev_speed) { + case USB_SPEED_LOW: + return USB_AUDIO_DEVICE_SPEED_LOW_V01; + case USB_SPEED_FULL: + return USB_AUDIO_DEVICE_SPEED_FULL_V01; + case USB_SPEED_HIGH: + return USB_AUDIO_DEVICE_SPEED_HIGH_V01; + case USB_SPEED_SUPER: + return USB_AUDIO_DEVICE_SPEED_SUPER_V01; + case USB_SPEED_SUPER_PLUS: + return USB_AUDIO_DEVICE_SPEED_SUPER_PLUS_V01; + default: + return USB_AUDIO_DEVICE_SPEED_INVALID_V01; + } +} + +/* Offloading IOMMU management */ +static unsigned long uaudio_get_iova(unsigned long *curr_iova, + size_t *curr_iova_size, struct list_head *head, size_t size) +{ + struct iova_info *info, *new_info = NULL; + struct list_head *curr_head; + unsigned long va = 0; + size_t tmp_size = size; + bool found = false; + + if (size % PAGE_SIZE) { + dev_err(uaudio_qdev->dev, "size %zu is not page size multiple\n", + size); + goto done; + } + + if (size > *curr_iova_size) { + dev_err(uaudio_qdev->dev, "size %zu > curr size %zu\n", + size, *curr_iova_size); + goto done; + } + if (*curr_iova_size == 0) { + dev_err(uaudio_qdev->dev, "iova mapping is full\n"); + goto done; + } + + list_for_each_entry(info, head, list) { + /* exact size iova_info */ + if (!info->in_use && info->size == size) { + info->in_use = true; + va = info->start_iova; + *curr_iova_size -= size; + found = true; + dev_dbg(uaudio_qdev->dev, "exact size: %zu found\n", size); + goto done; + } else if (!info->in_use && tmp_size >= info->size) { + if (!new_info) + new_info = info; + dev_dbg(uaudio_qdev->dev, "partial size: %zu found\n", + info->size); + tmp_size -= info->size; + if (tmp_size) + continue; + + va = new_info->start_iova; + for (curr_head = &new_info->list; curr_head != + &info->list; curr_head = curr_head->next) { + new_info = list_entry(curr_head, struct + iova_info, list); + new_info->in_use = true; + } + info->in_use = true; + *curr_iova_size -= size; + found = true; + goto done; + } else { + /* iova region in use */ + new_info = NULL; + tmp_size = size; + } + } + + info = kzalloc(sizeof(struct iova_info), GFP_KERNEL); + if (!info) { + va = 0; + goto done; + } + + va = info->start_iova = *curr_iova; + info->size = size; + info->in_use = true; + *curr_iova += size; + *curr_iova_size -= size; + found = true; + list_add_tail(&info->list, head); + +done: + if (!found) + dev_err(uaudio_qdev->dev, "unable to find %zu size iova\n", + size); + else + dev_dbg(uaudio_qdev->dev, + "va:0x%08lx curr_iova:0x%08lx curr_iova_size:%zu\n", + va, *curr_iova, *curr_iova_size); + + return va; +} + +/** + * uaudio_iommu_map() - maps iommu memory for adsp + * @mtype: ring type + * @dma_coherent: dma coherent + * @pa: physical address for ring/buffer + * @size: size of memory region + * @sgt: sg table for memory region + * + * Maps the XHCI related resources to a memory region that is assigned to be + * used by the adsp. This will be mapped to the domain, which is created by + * the ASoC USB backend driver. + * + */ +static unsigned long uaudio_iommu_map(enum mem_type mtype, bool dma_coherent, + phys_addr_t pa, size_t size, struct sg_table *sgt) +{ + unsigned long va_sg, va = 0; + bool map = true; + int i, ret; + size_t sg_len, total_len = 0; + struct scatterlist *sg; + phys_addr_t pa_sg; + int prot = IOMMU_READ | IOMMU_WRITE; + + if (dma_coherent) + prot |= IOMMU_CACHE; + + switch (mtype) { + case MEM_EVENT_RING: + va = IOVA_BASE; + /* er already mapped */ + if (uaudio_qdev->er_mapped) + map = false; + break; + case MEM_XFER_RING: + va = uaudio_get_iova(&uaudio_qdev->curr_xfer_ring_iova, + &uaudio_qdev->xfer_ring_iova_size, &uaudio_qdev->xfer_ring_list, + size); + break; + case MEM_XFER_BUF: + va = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova, + &uaudio_qdev->xfer_buf_iova_size, &uaudio_qdev->xfer_buf_list, + size); + break; + default: + dev_err(uaudio_qdev->dev, "unknown mem type %d\n", mtype); + } + + if (!va || !map) + goto done; + + if (!sgt) + goto skip_sgt_map; + + va_sg = va; + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + sg_len = PAGE_ALIGN(sg->offset + sg->length); + pa_sg = page_to_phys(sg_page(sg)); + ret = iommu_map(uaudio_qdev->domain, va_sg, pa_sg, sg_len, + prot); + if (ret) { + dev_err(uaudio_qdev->dev, "mapping failed ret%d\n", ret); + dev_err(uaudio_qdev->dev, + "type:%d, pa:%pa iova:0x%08lx sg_len:%zu\n", + mtype, &pa_sg, va_sg, sg_len); + uaudio_iommu_unmap(MEM_XFER_BUF, va, size, total_len); + va = 0; + goto done; + } + dev_dbg(uaudio_qdev->dev, + "type:%d map pa:%pa to iova:0x%08lx len:%zu offset:%u\n", + mtype, &pa_sg, va_sg, sg_len, sg->offset); + va_sg += sg_len; + total_len += sg_len; + } + + if (size != total_len) { + dev_err(uaudio_qdev->dev, "iova size %zu != mapped iova size %zu\n", + size, total_len); + uaudio_iommu_unmap(MEM_XFER_BUF, va, size, total_len); + va = 0; + } + return va; + +skip_sgt_map: + dev_dbg(uaudio_qdev->dev, "type:%d map pa:%pa to iova:0x%08lx size:%zu\n", + mtype, &pa, va, size); + + ret = iommu_map(uaudio_qdev->domain, va, pa, size, prot); + if (ret) + dev_err(uaudio_qdev->dev, + "failed to map pa:%pa iova:0x%lx type:%d ret:%d\n", + &pa, va, mtype, ret); +done: + return va; +} + +static void uaudio_put_iova(unsigned long va, size_t size, struct list_head + *head, size_t *curr_iova_size) +{ + struct iova_info *info; + size_t tmp_size = size; + bool found = false; + + list_for_each_entry(info, head, list) { + if (info->start_iova == va) { + if (!info->in_use) { + dev_err(uaudio_qdev->dev, "va %lu is not in use\n", + va); + return; + } + found = true; + info->in_use = false; + if (info->size == size) + goto done; + } + + if (found && tmp_size >= info->size) { + info->in_use = false; + tmp_size -= info->size; + if (!tmp_size) + goto done; + } + } + + if (!found) { + dev_err(uaudio_qdev->dev, "unable to find the va %lu\n", va); + return; + } +done: + *curr_iova_size += size; + dev_dbg(uaudio_qdev->dev, "curr_iova_size %zu\n", *curr_iova_size); +} + +/** + * uaudio_iommu_unmap() - unmaps iommu memory for adsp + * @mtype: ring type + * @va: virtual address to unmap + * @iova_size: region size + * @mapped_iova_size: mapped region size + * + * Unmaps the memory region that was previously assigned to the adsp. + * + */ +static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va, + size_t iova_size, size_t mapped_iova_size) +{ + size_t umap_size; + bool unmap = true; + + if (!va || !iova_size) + return; + + switch (mtype) { + case MEM_EVENT_RING: + if (uaudio_qdev->er_mapped) + uaudio_qdev->er_mapped = false; + else + unmap = false; + break; + + case MEM_XFER_RING: + uaudio_put_iova(va, iova_size, &uaudio_qdev->xfer_ring_list, + &uaudio_qdev->xfer_ring_iova_size); + break; + case MEM_XFER_BUF: + uaudio_put_iova(va, iova_size, &uaudio_qdev->xfer_buf_list, + &uaudio_qdev->xfer_buf_iova_size); + break; + default: + dev_err(uaudio_qdev->dev, "unknown mem type %d\n", mtype); + unmap = false; + } + + if (!unmap || !mapped_iova_size) + return; + + dev_dbg(uaudio_qdev->dev, "type %d: unmap iova 0x%08lx size %zu\n", + mtype, va, mapped_iova_size); + + umap_size = iommu_unmap(uaudio_qdev->domain, va, mapped_iova_size); + if (umap_size != mapped_iova_size) + dev_err(uaudio_qdev->dev, + "unmapped size %zu for iova 0x%08lx of mapped size %zu\n", + umap_size, va, mapped_iova_size); +} + +/* looks up alias, if any, for controller DT node and returns the index */ +static int usb_get_controller_id(struct usb_device *udev) +{ + if (udev->bus->sysdev && udev->bus->sysdev->of_node) + return of_alias_get_id(udev->bus->sysdev->of_node, "usb"); + + return -ENODEV; +} + +/** + * uaudio_dev_intf_cleanup() - cleanup transfer resources + * @udev: usb device + * @info: usb offloading interface + * + * Cleans up the transfer ring related resources which are assigned per + * endpoint from XHCI. This is invoked when the USB endpoints are no + * longer in use by the adsp. + * + */ +static void uaudio_dev_intf_cleanup(struct usb_device *udev, + struct intf_info *info) +{ + uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va, + info->data_xfer_ring_size, info->data_xfer_ring_size); + info->data_xfer_ring_va = 0; + info->data_xfer_ring_size = 0; + + uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va, + info->sync_xfer_ring_size, info->sync_xfer_ring_size); + info->sync_xfer_ring_va = 0; + info->sync_xfer_ring_size = 0; + + uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va, + info->xfer_buf_size, info->xfer_buf_size); + info->xfer_buf_va = 0; + + usb_free_coherent(udev, info->xfer_buf_size, + info->xfer_buf, info->xfer_buf_pa); + info->xfer_buf_size = 0; + info->xfer_buf = NULL; + info->xfer_buf_pa = 0; + + info->in_use = false; +} + +/** + * uaudio_event_ring_cleanup_free() - cleanup secondary event ring + * @dev: usb offload device + * + * Cleans up the secondary event ring that was requested. This will + * occur when the adsp is no longer transferring data on the USB bus + * across all endpoints. + * + */ +static void uaudio_event_ring_cleanup_free(struct uaudio_dev *dev) +{ + struct usb_hcd *hcd = bus_to_hcd(dev->udev->bus); + + clear_bit(dev->card_num, &uaudio_qdev->card_slot); + /* all audio devices are disconnected */ + if (!uaudio_qdev->card_slot) { + uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE, + PAGE_SIZE); + xhci_remove_secondary_interrupter(hcd, uaudio_qdev->ir); + uaudio_qdev->ir = NULL; + } +} + +/* kref release callback when all streams are disabled */ +static void uaudio_dev_release(struct kref *kref) +{ + struct uaudio_dev *dev = container_of(kref, struct uaudio_dev, kref); + + uaudio_event_ring_cleanup_free(dev); + atomic_set(&dev->in_use, 0); + wake_up(&dev->disconnect_wq); +} + +static struct snd_usb_substream *find_substream(unsigned int card_num, + unsigned int pcm_idx, unsigned int direction) +{ + struct snd_usb_stream *as; + struct snd_usb_substream *subs = NULL; + struct snd_usb_audio *chip; + + chip = uadev[card_num].chip; + if (!chip || atomic_read(&chip->shutdown)) + goto done; + + if (pcm_idx >= chip->pcm_devs) + goto done; + + if (direction > SNDRV_PCM_STREAM_CAPTURE) + goto done; + + list_for_each_entry(as, &chip->pcm_list, list) { + if (as->pcm_index == pcm_idx) { + subs = &as->substream[direction]; + goto done; + } + } + +done: + return subs; +} + +static int info_idx_from_ifnum(int card_num, int intf_num, bool enable) +{ + int i; + + /* + * default index 0 is used when info is allocated upon + * first enable audio stream req for a pcm device + */ + if (enable && !uadev[card_num].info) + return 0; + + for (i = 0; i < uadev[card_num].num_intf; i++) { + if (enable && !uadev[card_num].info[i].in_use) + return i; + else if (!enable && + uadev[card_num].info[i].intf_num == intf_num) + return i; + } + + return -EINVAL; +} + +static int get_data_interval_from_si(struct snd_usb_substream *subs, + u32 service_interval) +{ + unsigned int bus_intval, bus_intval_mult, binterval; + + if (subs->dev->speed >= USB_SPEED_HIGH) + bus_intval = BUS_INTERVAL_HIGHSPEED_AND_ABOVE; + else + bus_intval = BUS_INTERVAL_FULL_SPEED; + + if (service_interval % bus_intval) + return -EINVAL; + + bus_intval_mult = service_interval / bus_intval; + binterval = ffs(bus_intval_mult); + if (!binterval || binterval > MAX_BINTERVAL_ISOC_EP) + return -EINVAL; + + /* check if another bit is set then bail out */ + bus_intval_mult = bus_intval_mult >> binterval; + if (bus_intval_mult) + return -EINVAL; + + return (binterval - 1); +} + +/* maps audio format received over QMI to asound.h based pcm format */ +static snd_pcm_format_t map_pcm_format(enum usb_qmi_audio_format fmt_received) +{ + switch (fmt_received) { + case USB_QMI_PCM_FORMAT_S8: + return SNDRV_PCM_FORMAT_S8; + case USB_QMI_PCM_FORMAT_U8: + return SNDRV_PCM_FORMAT_U8; + case USB_QMI_PCM_FORMAT_S16_LE: + return SNDRV_PCM_FORMAT_S16_LE; + case USB_QMI_PCM_FORMAT_S16_BE: + return SNDRV_PCM_FORMAT_S16_BE; + case USB_QMI_PCM_FORMAT_U16_LE: + return SNDRV_PCM_FORMAT_U16_LE; + case USB_QMI_PCM_FORMAT_U16_BE: + return SNDRV_PCM_FORMAT_U16_BE; + case USB_QMI_PCM_FORMAT_S24_LE: + return SNDRV_PCM_FORMAT_S24_LE; + case USB_QMI_PCM_FORMAT_S24_BE: + return SNDRV_PCM_FORMAT_S24_BE; + case USB_QMI_PCM_FORMAT_U24_LE: + return SNDRV_PCM_FORMAT_U24_LE; + case USB_QMI_PCM_FORMAT_U24_BE: + return SNDRV_PCM_FORMAT_U24_BE; + case USB_QMI_PCM_FORMAT_S24_3LE: + return SNDRV_PCM_FORMAT_S24_3LE; + case USB_QMI_PCM_FORMAT_S24_3BE: + return SNDRV_PCM_FORMAT_S24_3BE; + case USB_QMI_PCM_FORMAT_U24_3LE: + return SNDRV_PCM_FORMAT_U24_3LE; + case USB_QMI_PCM_FORMAT_U24_3BE: + return SNDRV_PCM_FORMAT_U24_3BE; + case USB_QMI_PCM_FORMAT_S32_LE: + return SNDRV_PCM_FORMAT_S32_LE; + case USB_QMI_PCM_FORMAT_S32_BE: + return SNDRV_PCM_FORMAT_S32_BE; + case USB_QMI_PCM_FORMAT_U32_LE: + return SNDRV_PCM_FORMAT_U32_LE; + case USB_QMI_PCM_FORMAT_U32_BE: + return SNDRV_PCM_FORMAT_U32_BE; + default: + /* + * We expect the caller to do input validation so we should + * never hit this. But we do have to return a proper + * snd_pcm_format_t value due to the __bitwise attribute; so + * just return the equivalent of 0 in case of bad input. + */ + return SNDRV_PCM_FORMAT_S8; + } +} + +/** + * disable_audio_stream() - disable usb snd endpoints + * @subs: usb substream + * + * Closes the USB SND endpoints associated with the current audio stream + * used. This will decrement the USB SND endpoint opened reference count. + * + */ +static void disable_audio_stream(struct snd_usb_substream *subs) +{ + struct snd_usb_audio *chip = subs->stream->chip; + + if (subs->data_endpoint || subs->sync_endpoint) { + close_endpoints(chip, subs); + + mutex_lock(&chip->mutex); + subs->cur_audiofmt = NULL; + mutex_unlock(&chip->mutex); + } + + snd_usb_autosuspend(chip); +} + +/** + * enable_audio_stream() - enable usb snd endpoints + * @subs: usb substream + * @pcm_format: pcm format requested + * @channels: number of channels + * @cur_rate: sample rate + * @datainterval: interval + * + * Opens all USB SND endpoints used for the data interface. This will increment + * the USB SND endpoint's opened count. Requests to keep the interface resumed + * until the audio stream is stopped. Will issue the USB set interface control + * message to enable the data interface. + * + */ +static int enable_audio_stream(struct snd_usb_substream *subs, + snd_pcm_format_t pcm_format, + unsigned int channels, unsigned int cur_rate, + int datainterval) +{ + struct snd_usb_audio *chip = subs->stream->chip; + struct snd_pcm_hw_params params; + const struct audioformat *fmt; + int ret; + + _snd_pcm_hw_params_any(¶ms); + _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, + (__force int) pcm_format, 0); + _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, + channels, 0); + _snd_pcm_hw_param_set(¶ms, SNDRV_PCM_HW_PARAM_RATE, + cur_rate, 0); + + pm_runtime_barrier(&chip->intf[0]->dev); + snd_usb_autoresume(chip); + + fmt = find_format(&subs->fmt_list, pcm_format, cur_rate, + channels, datainterval, subs); + if (!fmt) { + dev_err(uaudio_qdev->dev, + "cannot find format: format = %#x, rate = %d, ch = %d\n", + pcm_format, cur_rate, channels); + return -EINVAL; + } + + if (atomic_read(&chip->shutdown)) { + dev_err(uaudio_qdev->dev, "chip already shutdown\n"); + ret = -ENODEV; + } else { + if (subs->data_endpoint) + close_endpoints(chip, subs); + + subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, + ¶ms, false); + if (!subs->data_endpoint) { + dev_err(uaudio_qdev->dev, "failed to open data endpoint\n"); + return -EINVAL; + } + + if (fmt->sync_ep) { + subs->sync_endpoint = snd_usb_endpoint_open(chip, + fmt, ¶ms, true); + if (!subs->sync_endpoint) { + dev_err(uaudio_qdev->dev, + "failed to open sync endpoint\n"); + return -EINVAL; + } + + subs->data_endpoint->sync_source = subs->sync_endpoint; + } + + mutex_lock(&chip->mutex); + subs->cur_audiofmt = fmt; + mutex_unlock(&chip->mutex); + + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (ret < 0) + return ret; + } + + ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); + if (ret < 0) + return ret; + + dev_dbg(uaudio_qdev->dev, + "selected %s iface:%d altsetting:%d datainterval:%dus\n", + subs->direction ? "capture" : "playback", + fmt->iface, fmt->altsetting, + (1 << fmt->datainterval) * + (subs->dev->speed >= USB_SPEED_HIGH ? + BUS_INTERVAL_HIGHSPEED_AND_ABOVE : + BUS_INTERVAL_FULL_SPEED)); + } + + return 0; +} + +/** + * prepare_qmi_response() - prepare stream enable response + * @subs: usb substream + * @req_msg: QMI request message + * @resp: QMI response buffer + * @info_idx: usb interface array index + * + * Prepares the QMI response for a USB QMI stream enable request. Will parse + * out the parameters within the stream enable request, in order to match + * requested audio profile to the ones exposed by the USB device connected. + * + * In addition, will fetch the XHCI transfer resources needed for the handoff to + * happen. This includes, transfer ring and buffer addresses and secondary event + * ring address. These parameters will be communicated as part of the USB QMI + * stream enable response. + * + */ +static int prepare_qmi_response(struct snd_usb_substream *subs, + struct qmi_uaudio_stream_req_msg_v01 *req_msg, + struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx) +{ + struct usb_interface *iface; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + struct usb_interface_assoc_descriptor *assoc; + struct usb_host_endpoint *ep; + struct uac_format_type_i_continuous_descriptor *fmt; + struct uac_format_type_i_discrete_descriptor *fmt_v1; + struct uac_format_type_i_ext_descriptor *fmt_v2; + struct uac1_as_header_descriptor *as; + struct xhci_interrupter *ir; + struct usb_hcd *hcd; + int ret; + int protocol, card_num, pcm_dev_num; + void *hdr_ptr; + u8 *xfer_buf; + unsigned int data_ep_pipe = 0, sync_ep_pipe = 0; + u32 len, mult, remainder, xfer_buf_len; + unsigned long va, tr_data_va = 0, tr_sync_va = 0; + phys_addr_t xhci_pa, xfer_buf_pa, tr_data_pa = 0, tr_sync_pa = 0; + dma_addr_t dma; + struct sg_table sgt; + bool dma_coherent; + + iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); + if (!iface) { + dev_err(uaudio_qdev->dev, "interface # %d does not exist\n", + subs->cur_audiofmt->iface); + ret = -ENODEV; + goto err; + } + + assoc = iface->intf_assoc; + pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8; + xfer_buf_len = req_msg->xfer_buff_size; + card_num = uaudio_qdev->last_card_num; + + alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; + altsd = get_iface_desc(alts); + protocol = altsd->bInterfaceProtocol; + + /* get format type */ + if (protocol != UAC_VERSION_3) { + fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, + UAC_FORMAT_TYPE); + if (!fmt) { + dev_err(uaudio_qdev->dev, + "%u:%d : no UAC_FORMAT_TYPE desc\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altset_idx); + ret = -ENODEV; + goto err; + } + } + + if (!uadev[card_num].ctrl_intf) { + dev_err(uaudio_qdev->dev, "audio ctrl intf info not cached\n"); + ret = -ENODEV; + goto err; + } + + if (protocol != UAC_VERSION_3) { + hdr_ptr = snd_usb_find_csint_desc(uadev[card_num].ctrl_intf->extra, + uadev[card_num].ctrl_intf->extralen, NULL, + UAC_HEADER); + if (!hdr_ptr) { + dev_err(uaudio_qdev->dev, "no UAC_HEADER desc\n"); + ret = -ENODEV; + goto err; + } + } + + if (protocol == UAC_VERSION_1) { + struct uac1_ac_header_descriptor *uac1_hdr = hdr_ptr; + + as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, + UAC_AS_GENERAL); + if (!as) { + dev_err(uaudio_qdev->dev, + "%u:%d : no UAC_AS_GENERAL desc\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altset_idx); + ret = -ENODEV; + goto err; + } + resp->data_path_delay = as->bDelay; + resp->data_path_delay_valid = 1; + fmt_v1 = (struct uac_format_type_i_discrete_descriptor *)fmt; + resp->usb_audio_subslot_size = fmt_v1->bSubframeSize; + resp->usb_audio_subslot_size_valid = 1; + + resp->usb_audio_spec_revision = le16_to_cpu(uac1_hdr->bcdADC); + resp->usb_audio_spec_revision_valid = 1; + } else if (protocol == UAC_VERSION_2) { + struct uac2_ac_header_descriptor *uac2_hdr = hdr_ptr; + + fmt_v2 = (struct uac_format_type_i_ext_descriptor *)fmt; + resp->usb_audio_subslot_size = fmt_v2->bSubslotSize; + resp->usb_audio_subslot_size_valid = 1; + + resp->usb_audio_spec_revision = le16_to_cpu(uac2_hdr->bcdADC); + resp->usb_audio_spec_revision_valid = 1; + } else if (protocol == UAC_VERSION_3) { + if (assoc->bFunctionSubClass == + UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0) { + dev_err(uaudio_qdev->dev, "full adc is not supported\n"); + ret = -EINVAL; + } + + switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) { + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16: + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16: + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16: + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16: { + resp->usb_audio_subslot_size = 0x2; + break; + } + + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24: + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24: + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24: + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24: { + resp->usb_audio_subslot_size = 0x3; + break; + } + + default: + dev_err(uaudio_qdev->dev, + "%d: %u: Invalid wMaxPacketSize\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altset_idx); + ret = -EINVAL; + goto err; + } + resp->usb_audio_subslot_size_valid = 1; + } else { + dev_err(uaudio_qdev->dev, "unknown protocol version %x\n", + protocol); + ret = -ENODEV; + goto err; + } + + resp->slot_id = subs->dev->slot_id; + resp->slot_id_valid = 1; + + memcpy(&resp->std_as_opr_intf_desc, &alts->desc, sizeof(alts->desc)); + resp->std_as_opr_intf_desc_valid = 1; + + ep = usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe); + if (!ep) { + dev_err(uaudio_qdev->dev, "data ep # %d context is null\n", + subs->data_endpoint->ep_num); + ret = -ENODEV; + goto err; + } + data_ep_pipe = subs->data_endpoint->pipe; + memcpy(&resp->std_as_data_ep_desc, &ep->desc, sizeof(ep->desc)); + resp->std_as_data_ep_desc_valid = 1; + + tr_data_pa = xhci_get_xfer_resource(subs->dev, ep, &dma); + if (!tr_data_pa) { + dev_err(uaudio_qdev->dev, "failed to get data ep ring address\n"); + ret = -ENODEV; + goto err; + } + resp->xhci_mem_info.tr_data.pa = dma; + + if (subs->sync_endpoint) { + ep = usb_pipe_endpoint(subs->dev, subs->sync_endpoint->pipe); + if (!ep) { + dev_err(uaudio_qdev->dev, "implicit fb on data ep\n"); + goto skip_sync_ep; + } + sync_ep_pipe = subs->sync_endpoint->pipe; + memcpy(&resp->std_as_sync_ep_desc, &ep->desc, sizeof(ep->desc)); + resp->std_as_sync_ep_desc_valid = 1; + + tr_sync_pa = xhci_get_xfer_resource(subs->dev, ep, &dma); + if (!tr_sync_pa) { + dev_err(uaudio_qdev->dev, + "failed to get sync ep ring address\n"); + ret = -ENODEV; + goto err; + } + resp->xhci_mem_info.tr_sync.pa = dma; + } + +skip_sync_ep: + resp->interrupter_num_valid = 1; + resp->controller_num_valid = 0; + ret = usb_get_controller_id(subs->dev); + if (ret >= 0) { + resp->controller_num = ret; + resp->controller_num_valid = 1; + } + /* map xhci data structures PA memory to iova */ + dma_coherent = dev_is_dma_coherent(subs->dev->bus->sysdev); + + /* event ring */ + hcd = bus_to_hcd(subs->dev->bus); + ir = xhci_create_secondary_interrupter(hcd, uaudio_qdev->intr_num); + if (!ir) { + dev_err(uaudio_qdev->dev, "failed to fetch interrupter\n"); + ret = -ENODEV; + goto err; + } + + xhci_pa = xhci_get_ir_resource(subs->dev, ir); + if (!xhci_pa) { + dev_err(uaudio_qdev->dev, + "failed to get sec event ring address\n"); + ret = -ENODEV; + goto free_sec_ring; + } + + uaudio_qdev->ir = ir; + resp->interrupter_num = ir->intr_num; + + va = uaudio_iommu_map(MEM_EVENT_RING, dma_coherent, xhci_pa, PAGE_SIZE, + NULL); + if (!va) { + ret = -ENOMEM; + goto free_sec_ring; + } + + resp->xhci_mem_info.evt_ring.va = PREPEND_SID_TO_IOVA(va, + uaudio_qdev->sid); + resp->xhci_mem_info.evt_ring.pa = ir->event_ring->first_seg->dma; + resp->xhci_mem_info.evt_ring.size = PAGE_SIZE; + uaudio_qdev->er_mapped = true; + + resp->speed_info = get_speed_info(subs->dev->speed); + if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01) { + ret = -ENODEV; + goto unmap_er; + } + + resp->speed_info_valid = 1; + + /* data transfer ring */ + va = uaudio_iommu_map(MEM_XFER_RING, dma_coherent, tr_data_pa, + PAGE_SIZE, NULL); + if (!va) { + ret = -ENOMEM; + goto unmap_er; + } + + tr_data_va = va; + resp->xhci_mem_info.tr_data.va = PREPEND_SID_TO_IOVA(va, + uaudio_qdev->sid); + resp->xhci_mem_info.tr_data.size = PAGE_SIZE; + + /* sync transfer ring */ + if (!resp->xhci_mem_info.tr_sync.pa) + goto skip_sync; + + xhci_pa = resp->xhci_mem_info.tr_sync.pa; + va = uaudio_iommu_map(MEM_XFER_RING, dma_coherent, tr_sync_pa, + PAGE_SIZE, NULL); + if (!va) { + ret = -ENOMEM; + goto unmap_data; + } + + tr_sync_va = va; + resp->xhci_mem_info.tr_sync.va = PREPEND_SID_TO_IOVA(va, + uaudio_qdev->sid); + resp->xhci_mem_info.tr_sync.size = PAGE_SIZE; + +skip_sync: + /* xfer buffer, multiple of 4K only */ + if (!xfer_buf_len) + xfer_buf_len = PAGE_SIZE; + + mult = xfer_buf_len / PAGE_SIZE; + remainder = xfer_buf_len % PAGE_SIZE; + len = mult * PAGE_SIZE; + len += remainder ? PAGE_SIZE : 0; + + if (len > MAX_XFER_BUFF_LEN) { + dev_err(uaudio_qdev->dev, + "req buf len %d > max buf len %lu, setting %lu\n", + len, MAX_XFER_BUFF_LEN, MAX_XFER_BUFF_LEN); + len = MAX_XFER_BUFF_LEN; + } + + xfer_buf = usb_alloc_coherent(subs->dev, len, GFP_KERNEL, &xfer_buf_pa); + if (!xfer_buf) { + ret = -ENOMEM; + goto unmap_sync; + } + + dma_get_sgtable(subs->dev->bus->sysdev, &sgt, xfer_buf, xfer_buf_pa, + len); + va = uaudio_iommu_map(MEM_XFER_BUF, dma_coherent, xfer_buf_pa, len, + &sgt); + if (!va) { + ret = -ENOMEM; + goto unmap_sync; + } + + resp->xhci_mem_info.xfer_buff.pa = xfer_buf_pa; + resp->xhci_mem_info.xfer_buff.size = len; + + resp->xhci_mem_info.xfer_buff.va = PREPEND_SID_TO_IOVA(va, + uaudio_qdev->sid); + + resp->xhci_mem_info_valid = 1; + + sg_free_table(&sgt); + + if (!atomic_read(&uadev[card_num].in_use)) { + kref_init(&uadev[card_num].kref); + init_waitqueue_head(&uadev[card_num].disconnect_wq); + uadev[card_num].num_intf = + subs->dev->config->desc.bNumInterfaces; + uadev[card_num].info = kcalloc(uadev[card_num].num_intf, + sizeof(struct intf_info), GFP_KERNEL); + if (!uadev[card_num].info) { + ret = -ENOMEM; + goto unmap_sync; + } + uadev[card_num].udev = subs->dev; + atomic_set(&uadev[card_num].in_use, 1); + } else { + kref_get(&uadev[card_num].kref); + } + + uadev[card_num].card_num = card_num; + uadev[card_num].usb_core_id = resp->controller_num; + + /* cache intf specific info to use it for unmap and free xfer buf */ + uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va; + uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE; + uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va; + uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE; + uadev[card_num].info[info_idx].xfer_buf_va = va; + uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa; + uadev[card_num].info[info_idx].xfer_buf_size = len; + uadev[card_num].info[info_idx].data_ep_pipe = data_ep_pipe; + uadev[card_num].info[info_idx].sync_ep_pipe = sync_ep_pipe; + uadev[card_num].info[info_idx].xfer_buf = xfer_buf; + uadev[card_num].info[info_idx].pcm_card_num = card_num; + uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num; + uadev[card_num].info[info_idx].direction = subs->direction; + uadev[card_num].info[info_idx].intf_num = subs->cur_audiofmt->iface; + uadev[card_num].info[info_idx].in_use = true; + + set_bit(card_num, &uaudio_qdev->card_slot); + + return 0; + +unmap_sync: + usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_pa); + uaudio_iommu_unmap(MEM_XFER_RING, tr_sync_va, PAGE_SIZE, PAGE_SIZE); +unmap_data: + uaudio_iommu_unmap(MEM_XFER_RING, tr_data_va, PAGE_SIZE, PAGE_SIZE); +unmap_er: + uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE, PAGE_SIZE); +free_sec_ring: + xhci_remove_secondary_interrupter(hcd, uaudio_qdev->ir); +err: + return ret; +} + +/** + * handle_uaudio_stream_req() - handle stream enable/disable request + * @handle: QMI client handle + * @sq: qrtr socket + * @txn: QMI transaction context + * @decoded_msg: decoded QMI message + * + * Main handler for the QMI stream enable/disable requests. This executes the + * corresponding enable/disable stream apis, respectively. + * + */ +static void handle_uaudio_stream_req(struct qmi_handle *handle, + struct sockaddr_qrtr *sq, + struct qmi_txn *txn, + const void *decoded_msg) +{ + struct qmi_uaudio_stream_req_msg_v01 *req_msg; + struct qmi_uaudio_stream_resp_msg_v01 resp = {{0}, 0}; + struct snd_usb_substream *subs; + struct snd_usb_audio *chip = NULL; + struct uaudio_qmi_svc *svc = uaudio_svc; + struct intf_info *info; + struct usb_host_endpoint *ep; + u8 pcm_card_num, pcm_dev_num, direction; + int info_idx = -EINVAL, datainterval = -EINVAL, ret = 0; + + if (!svc->client_connected) { + svc->client_sq = *sq; + svc->client_connected = true; + } + + req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)decoded_msg; + if (!req_msg->audio_format_valid || !req_msg->bit_rate_valid || + !req_msg->number_of_ch_valid || !req_msg->xfer_buff_size_valid) { + ret = -EINVAL; + goto response; + } + + mutex_lock(&qdev_mutex); + if (!uaudio_qdev) { + mutex_unlock(&qdev_mutex); + ret = -EINVAL; + goto response; + } + + direction = (req_msg->usb_token & SND_PCM_STREAM_DIRECTION); + pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8; + pcm_card_num = req_msg->enable ? uaudio_qdev->last_card_num : + ffs(uaudio_qdev->card_slot) - 1; + mutex_unlock(&qdev_mutex); + if (pcm_card_num >= SNDRV_CARDS) { + ret = -EINVAL; + goto response; + } + + if (req_msg->audio_format > USB_QMI_PCM_FORMAT_U32_BE) { + ret = -EINVAL; + goto response; + } + + subs = find_substream(pcm_card_num, pcm_dev_num, direction); + chip = uadev[pcm_card_num].chip; + if (!subs || !chip || atomic_read(&chip->shutdown)) { + ret = -ENODEV; + goto response; + } + + info_idx = info_idx_from_ifnum(pcm_card_num, subs->cur_audiofmt ? + subs->cur_audiofmt->iface : -1, req_msg->enable); + if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm + || !subs->stream->chip) { + ret = -ENODEV; + goto response; + } + + if (req_msg->enable) { + if (info_idx < 0 || chip->system_suspend) { + ret = -EBUSY; + goto response; + } + } + + if (req_msg->service_interval_valid) { + ret = get_data_interval_from_si(subs, + req_msg->service_interval); + if (ret == -EINVAL) + goto response; + + datainterval = ret; + } + + uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf; + + if (req_msg->enable) { + ret = enable_audio_stream(subs, + map_pcm_format(req_msg->audio_format), + req_msg->number_of_ch, req_msg->bit_rate, + datainterval); + + if (!ret) + ret = prepare_qmi_response(subs, req_msg, &resp, + info_idx); + } else { + info = &uadev[pcm_card_num].info[info_idx]; + if (info->data_ep_pipe) { + ep = usb_pipe_endpoint(uadev[pcm_card_num].udev, + info->data_ep_pipe); + if (ep) + xhci_stop_endpoint(uadev[pcm_card_num].udev, + ep); + info->data_ep_pipe = 0; + } + + if (info->sync_ep_pipe) { + ep = usb_pipe_endpoint(uadev[pcm_card_num].udev, + info->sync_ep_pipe); + if (ep) + xhci_stop_endpoint(uadev[pcm_card_num].udev, + ep); + info->sync_ep_pipe = 0; + } + + disable_audio_stream(subs); + } + +response: + if (!req_msg->enable && ret != -EINVAL && ret != -ENODEV) { + mutex_lock(&chip->mutex); + if (info_idx >= 0) { + info = &uadev[pcm_card_num].info[info_idx]; + uaudio_dev_intf_cleanup( + uadev[pcm_card_num].udev, + info); + } + if (atomic_read(&uadev[pcm_card_num].in_use)) + kref_put(&uadev[pcm_card_num].kref, + uaudio_dev_release); + mutex_unlock(&chip->mutex); + } + + resp.usb_token = req_msg->usb_token; + resp.usb_token_valid = 1; + resp.internal_status = ret; + resp.internal_status_valid = 1; + resp.status = ret ? USB_AUDIO_STREAM_REQ_FAILURE_V01 : ret; + resp.status_valid = 1; + ret = qmi_send_response(svc->uaudio_svc_hdl, sq, txn, + QMI_UAUDIO_STREAM_RESP_V01, + QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN, + qmi_uaudio_stream_resp_msg_v01_ei, &resp); +} + +static struct qmi_msg_handler uaudio_stream_req_handlers = { + .type = QMI_REQUEST, + .msg_id = QMI_UAUDIO_STREAM_REQ_V01, + .ei = qmi_uaudio_stream_req_msg_v01_ei, + .decoded_size = QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN, + .fn = handle_uaudio_stream_req, +}; + +/* returns usb hcd sysdev */ +static struct device *usb_get_usb_backend(struct usb_device *udev) +{ + if (udev->bus->sysdev && udev->bus->sysdev->of_node) + return udev->bus->sysdev; + + return NULL; +} + +/** + * qc_usb_audio_offload_init_qmi_dev() - initializes qmi dev + * + * Initializes the USB qdev, which is used to carry information pertaining to + * the offloading resources. This device is freed only when there are no longer + * any offloading candidates. (i.e, when all audio devices are disconnected) + * + */ +static int qc_usb_audio_offload_init_qmi_dev(struct usb_device *udev) +{ + struct q6usb_offload *data; + + uaudio_qdev = kzalloc(sizeof(struct uaudio_qmi_dev), + GFP_KERNEL); + if (!uaudio_qdev) + return -ENOMEM; + + /* initialize xfer ring and xfer buf iova list */ + INIT_LIST_HEAD(&uaudio_qdev->xfer_ring_list); + uaudio_qdev->curr_xfer_ring_iova = IOVA_XFER_RING_BASE; + uaudio_qdev->xfer_ring_iova_size = + IOVA_XFER_RING_MAX - IOVA_XFER_RING_BASE; + + INIT_LIST_HEAD(&uaudio_qdev->xfer_buf_list); + uaudio_qdev->curr_xfer_buf_iova = IOVA_XFER_BUF_BASE; + uaudio_qdev->xfer_buf_iova_size = + IOVA_XFER_BUF_MAX - IOVA_XFER_BUF_BASE; + + data = snd_soc_usb_get_priv_data(usb_get_usb_backend(udev)); + if (data) { + uaudio_qdev->domain = data->domain; + uaudio_qdev->sid = data->sid; + uaudio_qdev->intr_num = data->intr_num; + uaudio_qdev->dev = data->dev; + } + + return 0; +} + +/** + * qc_usb_audio_offload_probe() - platform op connect handler + * @intf: USB interface + * @chip: USB SND device + * + * Platform connect handler when a USB SND device is detected. Will + * notify SOC USB about the connection to enable the USB ASoC backend + * and populate internal USB chip array. + * + */ +static void qc_usb_audio_offload_probe(struct usb_interface *intf, + struct snd_usb_audio *chip) +{ + struct usb_device *udev = interface_to_usbdev(intf); + + mutex_lock(&chip->mutex); + if (!uaudio_qdev) + qc_usb_audio_offload_init_qmi_dev(udev); + + atomic_inc(&uaudio_qdev->qdev_in_use); + uadev[chip->card->number].chip = chip; + uaudio_qdev->last_card_num = chip->card->number; + + snd_soc_usb_connect(usb_get_usb_backend(udev), chip->index); + mutex_unlock(&chip->mutex); +} + +static void uaudio_dev_cleanup(struct uaudio_dev *dev) +{ + int if_idx; + + if (!dev->udev) + return; + + /* free xfer buffer and unmap xfer ring and buf per interface */ + for (if_idx = 0; if_idx < dev->num_intf; if_idx++) { + if (!dev->info[if_idx].in_use) + continue; + uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]); + dev_dbg(uaudio_qdev->dev, "release resources: intf# %d card# %d\n", + dev->info[if_idx].intf_num, dev->card_num); + } + + dev->num_intf = 0; + + /* free interface info */ + kfree(dev->info); + dev->info = NULL; + uaudio_event_ring_cleanup_free(dev); + dev->udev = NULL; +} + +/** + * qc_usb_audio_cleanup_qmi_dev() - release qmi device + * + * Frees the USB qdev. Only occurs when there are no longer any potential + * devices that can utilize USB audio offloading. + * + */ +static void qc_usb_audio_cleanup_qmi_dev(void) +{ + kfree(uaudio_qdev); + uaudio_qdev = NULL; +} + +/** + * qc_usb_audio_offload_disconnect() - platform op disconnect handler + * @intf: USB interface + * + * Platform disconnect handler. Will ensure that any pending stream is + * halted by issuing a QMI disconnect indication packet to the adsp. + * + */ +static void qc_usb_audio_offload_disconnect(struct usb_interface *intf) +{ + struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct usb_device *udev = interface_to_usbdev(intf); + struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0}; + struct uaudio_qmi_svc *svc = uaudio_svc; + struct uaudio_dev *dev; + int card_num; + int ret; + + if (!chip) + return; + + card_num = chip->card->number; + if (card_num >= SNDRV_CARDS) + return; + + + mutex_lock(&chip->mutex); + dev = &uadev[card_num]; + + /* clean up */ + if (!dev->udev) + goto done; + + if (atomic_read(&dev->in_use)) { + mutex_unlock(&chip->mutex); + dev_dbg(uaudio_qdev->dev, "sending qmi indication disconnect\n"); + disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01; + disconnect_ind.slot_id = dev->udev->slot_id; + disconnect_ind.controller_num = dev->usb_core_id; + disconnect_ind.controller_num_valid = 1; + ret = qmi_send_indication(svc->uaudio_svc_hdl, &svc->client_sq, + QMI_UAUDIO_STREAM_IND_V01, + QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN, + qmi_uaudio_stream_ind_msg_v01_ei, + &disconnect_ind); + if (ret < 0) + dev_err(uaudio_qdev->dev, + "qmi send failed with err: %d\n", ret); + + ret = wait_event_interruptible_timeout(dev->disconnect_wq, + !atomic_read(&dev->in_use), + msecs_to_jiffies(DEV_RELEASE_WAIT_TIMEOUT)); + if (!ret) { + dev_err(uaudio_qdev->dev, + "timeout while waiting for dev_release\n"); + atomic_set(&dev->in_use, 0); + } else if (ret < 0) { + dev_err(uaudio_qdev->dev, "failed with ret %d\n", ret); + atomic_set(&dev->in_use, 0); + } + mutex_lock(&chip->mutex); + } + + uaudio_dev_cleanup(dev); +done: + uadev[card_num].chip = NULL; + mutex_unlock(&chip->mutex); + + atomic_dec(&uaudio_qdev->qdev_in_use); + if (!atomic_read(&uaudio_qdev->qdev_in_use)) { + snd_soc_usb_disconnect(usb_get_usb_backend(udev)); + mutex_lock(&qdev_mutex); + qc_usb_audio_cleanup_qmi_dev(); + mutex_unlock(&qdev_mutex); + } +} + +/** + * qc_usb_audio_offload_suspend() - USB offload PM suspend handler + * @intf: USB interface + * @message: suspend type + * + * PM suspend handler to ensure that the USB offloading driver is able to stop + * any pending traffic, so that the bus can be suspended. + * + */ +static void qc_usb_audio_offload_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0}; + struct uaudio_qmi_svc *svc = uaudio_svc; + struct uaudio_dev *dev; + int card_num; + int ret; + + if (!chip) + return; + + card_num = chip->card->number; + if (card_num >= SNDRV_CARDS) + return; + + + mutex_lock(&chip->mutex); + dev = &uadev[card_num]; + + if (atomic_read(&dev->in_use)) { + mutex_unlock(&chip->mutex); + dev_dbg(uaudio_qdev->dev, "sending qmi indication suspend\n"); + disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01; + disconnect_ind.slot_id = dev->udev->slot_id; + disconnect_ind.controller_num = dev->usb_core_id; + disconnect_ind.controller_num_valid = 1; + ret = qmi_send_indication(svc->uaudio_svc_hdl, &svc->client_sq, + QMI_UAUDIO_STREAM_IND_V01, + QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN, + qmi_uaudio_stream_ind_msg_v01_ei, + &disconnect_ind); + if (ret < 0) + dev_err(uaudio_qdev->dev, + "qmi send failed with err: %d\n", ret); + + ret = wait_event_interruptible_timeout(dev->disconnect_wq, + !atomic_read(&dev->in_use), + msecs_to_jiffies(DEV_RELEASE_WAIT_TIMEOUT)); + if (!ret) { + dev_err(uaudio_qdev->dev, + "timeout while waiting for dev_release\n"); + atomic_set(&dev->in_use, 0); + } else if (ret < 0) { + dev_err(uaudio_qdev->dev, "failed with ret %d\n", ret); + atomic_set(&dev->in_use, 0); + } + mutex_lock(&chip->mutex); + } + mutex_unlock(&chip->mutex); +} + +static struct snd_usb_platform_ops offload_ops = { + .connect_cb = qc_usb_audio_offload_probe, + .disconnect_cb = qc_usb_audio_offload_disconnect, + .suspend_cb = qc_usb_audio_offload_suspend, +}; + +static int __init qc_usb_audio_offload_init(void) +{ + struct uaudio_qmi_svc *svc; + int ret; + + ret = snd_usb_register_platform_ops(&offload_ops); + if (ret < 0) + return ret; + + svc = kzalloc(sizeof(struct uaudio_qmi_svc), GFP_KERNEL); + if (!svc) { + ret = -ENOMEM; + goto unreg_ops; + } + + svc->uaudio_wq = create_singlethread_workqueue("uaudio_svc"); + if (!svc->uaudio_wq) { + ret = -ENOMEM; + goto free_svc; + } + + svc->uaudio_svc_hdl = kzalloc(sizeof(struct qmi_handle), GFP_KERNEL); + if (!svc->uaudio_svc_hdl) { + ret = -ENOMEM; + goto free_wq; + } + + ret = qmi_handle_init(svc->uaudio_svc_hdl, + QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN, + &uaudio_svc_ops_options, + &uaudio_stream_req_handlers); + ret = qmi_add_server(svc->uaudio_svc_hdl, UAUDIO_STREAM_SERVICE_ID_V01, + UAUDIO_STREAM_SERVICE_VERS_V01, 0); + + INIT_WORK(&svc->qmi_disconnect_work, qmi_disconnect_work); + uaudio_svc = svc; + + return 0; + +free_wq: + destroy_workqueue(svc->uaudio_wq); +free_svc: + kfree(svc); +unreg_ops: + snd_usb_unregister_platform_ops(); + + return ret; +} + +static void __exit qc_usb_audio_offload_exit(void) +{ + struct uaudio_qmi_svc *svc = uaudio_svc; + + qmi_handle_release(svc->uaudio_svc_hdl); + flush_workqueue(svc->uaudio_wq); + destroy_workqueue(svc->uaudio_wq); + kfree(svc); + uaudio_svc = NULL; + snd_usb_unregister_platform_ops(); +} + +module_init(qc_usb_audio_offload_init); +module_exit(qc_usb_audio_offload_exit); + +MODULE_DESCRIPTION("QC USB Audio Offloading"); +MODULE_LICENSE("GPL"); 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..95ae434f0a41 --- /dev/null +++ b/sound/usb/qcom/usb_audio_qmi_v01.c @@ -0,0 +1,892 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include + +#include "usb_audio_qmi_v01.h" + +static struct qmi_elem_info mem_info_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct mem_info_v01, va), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct mem_info_v01, pa), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct mem_info_v01, size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info apps_mem_info_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct apps_mem_info_v01, evt_ring), + .ei_array = mem_info_v01_ei, + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct apps_mem_info_v01, tr_data), + .ei_array = mem_info_v01_ei, + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct apps_mem_info_v01, tr_sync), + .ei_array = mem_info_v01_ei, + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct apps_mem_info_v01, xfer_buff), + .ei_array = mem_info_v01_ei, + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct apps_mem_info_v01, dcba), + .ei_array = mem_info_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info usb_endpoint_descriptor_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bLength), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bDescriptorType), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bEndpointAddress), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bmAttributes), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + wMaxPacketSize), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bInterval), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bRefresh), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_endpoint_descriptor_v01, + bSynchAddress), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info usb_interface_descriptor_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bLength), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bDescriptorType), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bInterfaceNumber), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bAlternateSetting), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bNumEndpoints), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bInterfaceClass), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bInterfaceSubClass), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + bInterfaceProtocol), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct usb_interface_descriptor_v01, + iInterface), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info qmi_uaudio_stream_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + enable), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + usb_token), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + audio_format_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + audio_format), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + number_of_ch_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + number_of_ch), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + bit_rate_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + bit_rate), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + xfer_buff_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + xfer_buff_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + service_interval_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct qmi_uaudio_stream_req_msg_v01, + service_interval), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info qmi_uaudio_stream_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + status_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum usb_audio_stream_status_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + status), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + internal_status_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + internal_status), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + slot_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + slot_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_token_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_token), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_opr_intf_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_interface_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_opr_intf_desc), + .ei_array = usb_interface_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_data_ep_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_endpoint_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_data_ep_desc), + .ei_array = usb_endpoint_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_sync_ep_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_endpoint_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + std_as_sync_ep_desc), + .ei_array = usb_endpoint_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_audio_spec_revision_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_audio_spec_revision), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + data_path_delay_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + data_path_delay), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_audio_subslot_size_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + usb_audio_subslot_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + xhci_mem_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct apps_mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + xhci_mem_info), + .ei_array = apps_mem_info_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + interrupter_num_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + interrupter_num), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + speed_info_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum usb_audio_device_speed_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + speed_info), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + controller_num_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof( + struct qmi_uaudio_stream_resp_msg_v01, + controller_num), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info qmi_uaudio_stream_ind_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof( + enum usb_audio_device_indication_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + dev_event), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + slot_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_token_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_token), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_opr_intf_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_interface_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_opr_intf_desc), + .ei_array = usb_interface_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_data_ep_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_endpoint_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_data_ep_desc), + .ei_array = usb_endpoint_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_sync_ep_desc_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct usb_endpoint_descriptor_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + std_as_sync_ep_desc), + .ei_array = usb_endpoint_descriptor_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_audio_spec_revision_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_audio_spec_revision), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + data_path_delay_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + data_path_delay), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_audio_subslot_size_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + usb_audio_subslot_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + xhci_mem_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct apps_mem_info_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + xhci_mem_info), + .ei_array = apps_mem_info_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + interrupter_num_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + interrupter_num), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + controller_num_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct qmi_uaudio_stream_ind_msg_v01, + controller_num), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; 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..4e9b5f0bcddf --- /dev/null +++ b/sound/usb/qcom/usb_audio_qmi_v01.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef USB_QMI_V01_H +#define USB_QMI_V01_H + +#define UAUDIO_STREAM_SERVICE_ID_V01 0x41D +#define UAUDIO_STREAM_SERVICE_VERS_V01 0x01 + +#define QMI_UAUDIO_STREAM_RESP_V01 0x0001 +#define QMI_UAUDIO_STREAM_REQ_V01 0x0001 +#define QMI_UAUDIO_STREAM_IND_V01 0x0001 + + +struct mem_info_v01 { + u64 va; + u64 pa; + u32 size; +}; + +struct apps_mem_info_v01 { + struct mem_info_v01 evt_ring; + struct mem_info_v01 tr_data; + struct mem_info_v01 tr_sync; + struct mem_info_v01 xfer_buff; + struct mem_info_v01 dcba; +}; + +struct usb_endpoint_descriptor_v01 { + u8 bLength; + u8 bDescriptorType; + u8 bEndpointAddress; + u8 bmAttributes; + u16 wMaxPacketSize; + u8 bInterval; + u8 bRefresh; + u8 bSynchAddress; +}; + +struct usb_interface_descriptor_v01 { + u8 bLength; + u8 bDescriptorType; + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +}; + +enum usb_audio_stream_status_enum_v01 { + USB_AUDIO_STREAM_STATUS_ENUM_MIN_VAL_V01 = INT_MIN, + USB_AUDIO_STREAM_REQ_SUCCESS_V01 = 0, + USB_AUDIO_STREAM_REQ_FAILURE_V01 = 1, + USB_AUDIO_STREAM_REQ_FAILURE_NOT_FOUND_V01 = 2, + USB_AUDIO_STREAM_REQ_FAILURE_INVALID_PARAM_V01 = 3, + USB_AUDIO_STREAM_REQ_FAILURE_MEMALLOC_V01 = 4, + USB_AUDIO_STREAM_STATUS_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum usb_audio_device_indication_enum_v01 { + USB_AUDIO_DEVICE_INDICATION_ENUM_MIN_VAL_V01 = INT_MIN, + USB_AUDIO_DEV_CONNECT_V01 = 0, + USB_AUDIO_DEV_DISCONNECT_V01 = 1, + USB_AUDIO_DEV_SUSPEND_V01 = 2, + USB_AUDIO_DEV_RESUME_V01 = 3, + USB_AUDIO_DEVICE_INDICATION_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum usb_audio_device_speed_enum_v01 { + USB_AUDIO_DEVICE_SPEED_ENUM_MIN_VAL_V01 = INT_MIN, + USB_AUDIO_DEVICE_SPEED_INVALID_V01 = 0, + USB_AUDIO_DEVICE_SPEED_LOW_V01 = 1, + USB_AUDIO_DEVICE_SPEED_FULL_V01 = 2, + USB_AUDIO_DEVICE_SPEED_HIGH_V01 = 3, + USB_AUDIO_DEVICE_SPEED_SUPER_V01 = 4, + USB_AUDIO_DEVICE_SPEED_SUPER_PLUS_V01 = 5, + USB_AUDIO_DEVICE_SPEED_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +struct qmi_uaudio_stream_req_msg_v01 { + u8 enable; + u32 usb_token; + u8 audio_format_valid; + u32 audio_format; + u8 number_of_ch_valid; + u32 number_of_ch; + u8 bit_rate_valid; + u32 bit_rate; + u8 xfer_buff_size_valid; + u32 xfer_buff_size; + u8 service_interval_valid; + u32 service_interval; +}; +#define QMI_UAUDIO_STREAM_REQ_MSG_V01_MAX_MSG_LEN 46 +extern struct qmi_elem_info qmi_uaudio_stream_req_msg_v01_ei[]; + +struct qmi_uaudio_stream_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 status_valid; + enum usb_audio_stream_status_enum_v01 status; + u8 internal_status_valid; + u32 internal_status; + u8 slot_id_valid; + u32 slot_id; + u8 usb_token_valid; + u32 usb_token; + u8 std_as_opr_intf_desc_valid; + struct usb_interface_descriptor_v01 std_as_opr_intf_desc; + u8 std_as_data_ep_desc_valid; + struct usb_endpoint_descriptor_v01 std_as_data_ep_desc; + u8 std_as_sync_ep_desc_valid; + struct usb_endpoint_descriptor_v01 std_as_sync_ep_desc; + u8 usb_audio_spec_revision_valid; + u16 usb_audio_spec_revision; + u8 data_path_delay_valid; + u8 data_path_delay; + u8 usb_audio_subslot_size_valid; + u8 usb_audio_subslot_size; + u8 xhci_mem_info_valid; + struct apps_mem_info_v01 xhci_mem_info; + u8 interrupter_num_valid; + u8 interrupter_num; + u8 speed_info_valid; + enum usb_audio_device_speed_enum_v01 speed_info; + u8 controller_num_valid; + u8 controller_num; +}; +#define QMI_UAUDIO_STREAM_RESP_MSG_V01_MAX_MSG_LEN 202 +extern struct qmi_elem_info qmi_uaudio_stream_resp_msg_v01_ei[]; + +struct qmi_uaudio_stream_ind_msg_v01 { + enum usb_audio_device_indication_enum_v01 dev_event; + u32 slot_id; + u8 usb_token_valid; + u32 usb_token; + u8 std_as_opr_intf_desc_valid; + struct usb_interface_descriptor_v01 std_as_opr_intf_desc; + u8 std_as_data_ep_desc_valid; + struct usb_endpoint_descriptor_v01 std_as_data_ep_desc; + u8 std_as_sync_ep_desc_valid; + struct usb_endpoint_descriptor_v01 std_as_sync_ep_desc; + u8 usb_audio_spec_revision_valid; + u16 usb_audio_spec_revision; + u8 data_path_delay_valid; + u8 data_path_delay; + u8 usb_audio_subslot_size_valid; + u8 usb_audio_subslot_size; + u8 xhci_mem_info_valid; + struct apps_mem_info_v01 xhci_mem_info; + u8 interrupter_num_valid; + u8 interrupter_num; + u8 controller_num_valid; + u8 controller_num; +}; +#define QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN 181 +extern struct qmi_elem_info qmi_uaudio_stream_ind_msg_v01_ei[]; + +#endif From patchwork Thu Jan 26 03:14:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48466 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69359wrn; Wed, 25 Jan 2023 19:16:25 -0800 (PST) X-Google-Smtp-Source: AMrXdXsi+aM1okzDzZLsnNeDfB37Hnh47XxpQNM4tEXl4ZTN9tkPnXratQoLz/qI8JiAVtKuNeRn X-Received: by 2002:a05:6a20:c189:b0:b8:6168:bc2e with SMTP id bg9-20020a056a20c18900b000b86168bc2emr39904399pzb.52.1674702984801; Wed, 25 Jan 2023 19:16:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702984; cv=none; d=google.com; s=arc-20160816; b=0TIPHZKtMRYL1w8+jwcHdXbYlBKM0Ods0834AP6rxZW42v9NsnVgkzHjAdWLohQgPQ fQxaSbI6yjeCfPhrzcd6hzSir0DCEPfFpkKcBlnASHAtOP2ncUrnXT5mHfWBvdW85vqX /a8RFltS76zc7egqF3qCnjeBDx9IvD/lJ5SWdsKrd3W3a3r2oM4YU9+6loE60/N1VHNe cRIB6iL+PCi/Y3Xw42isf90s1CxLDqddSpM9SDWojNjNV5mlr0ptLxYvpprCB090UsKT Szh80MzYg5KCRHLGS+pMN44Tv3YybxCKIhVPJtNLkMo9Dej4bejT262EmKTC+LHP0jj6 J2hw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=/Ys3+vP/SR8aiAN4HzahjXM1RRlJ/QH4E8Ntv69ejEQ=; b=nQehTpDjVKiYTOILP++5dtiDTbMLE1iX2vLRI7+5zqtV0g+vOGCFF8CmACH/Vuy133 Q+42eR0nPjL31KqpHO85M6HhsA9WREwKTK3Ci3MpSZ5w8qBzBJu5FQM1ehC2R/I2Mmjh sBHcRYA/T4U5PTxOmT2LgLceZw8TJB+guR5s+sGtrZU9Q+Qk/Q0tvH4sRAOP/4DP6l0A DrWum85NtcwtaPVqrEkLhXJ/vGqiG2WPhnDrxdsjpXZmG83GcNj3mV1cY6LQeRa0TBtM Abni9BsHaFIwi+aWdjfkDdeh/SbbZ7mjWS+28dM/EOCqInVGh2tZ1CIplH2n68S7Q+jH eFTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=ELmmCvDZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v63-20020a638942000000b004c76dcc99c2si7571241pgd.334.2023.01.25.19.16.12; Wed, 25 Jan 2023 19:16:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=ELmmCvDZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236115AbjAZDPo (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45112 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236141AbjAZDPj (ORCPT ); Wed, 25 Jan 2023 22:15:39 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8415A65F33; Wed, 25 Jan 2023 19:15:07 -0800 (PST) Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q2va2S018786; Thu, 26 Jan 2023 03:14:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=/Ys3+vP/SR8aiAN4HzahjXM1RRlJ/QH4E8Ntv69ejEQ=; b=ELmmCvDZ9+WCF14SiSiDuH5RQ1Z7hn8gSHVnFvAT5JbLuVtHFSJ48UZLWZ2MvP0HHRxd 2SXmOPQWAEVVRtX9bBs9rNkIfI7ieiRMvy7ovuuYQ+sUlFG0NRC3NYEbaxAqzh2XEtgf 7/4dILqIlWMQ3VmgJnHt5RVFuAmJP1V64A0/hFldVGgCctpaEiD+B+tGmdc5YNAVA4UH 0LX80m++RpHzb8QyzLhOXaKv0Xigt8CriJb44ku+56Ik8A6Ew2ID/ZV9eQ5UGtgbXeJ9 8VjrNc+cc9UddSguQZHCt3EwpXHwxmd0gJv/5A1jHYqHywsAAiMATByPbC+/wqRGYEk7 HQ== Received: from nasanppmta02.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nbd7arbm9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:49 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA02.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EmJM031672 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:48 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:47 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 17/22] sound: usb: card: Check for support for requested audio format Date: Wed, 25 Jan 2023 19:14:19 -0800 Message-ID: <20230126031424.14582-18-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: w3DrZv4JekBRL12Ama70yMbCy-AyGu0X X-Proofpoint-GUID: w3DrZv4JekBRL12Ama70yMbCy-AyGu0X X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 impostorscore=0 adultscore=0 clxscore=1015 priorityscore=1501 phishscore=0 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053357413197155?= X-GMAIL-MSGID: =?utf-8?q?1756053357413197155?= Allow for checks on a specific USB audio device to see if a requested PCM format is supported. This is needed for support for when playback is initiated by the ASoC USB backend path. Signed-off-by: Wesley Cheng --- sound/usb/card.c | 28 ++++++++++++++++++++++++++++ sound/usb/card.h | 8 ++++++++ 2 files changed, 36 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index 59be5f543315..be06d19ee935 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -136,6 +136,34 @@ int snd_usb_unregister_platform_ops(void) } EXPORT_SYMBOL_GPL(snd_usb_unregister_platform_ops); +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 = usb_chip[card_idx]; + struct snd_usb_substream *subs = NULL; + struct snd_usb_stream *as; + const struct audioformat *fmt; + + if (!chip) + return NULL; + + mutex_lock(&chip->mutex); + if (enable[card_idx]) { + list_for_each_entry(as, &chip->pcm_list, list) { + subs = &as->substream[direction]; + fmt = find_substream_format(subs, params); + if (fmt) { + mutex_unlock(&chip->mutex); + return as; + } + } + } + mutex_unlock(&chip->mutex); + + 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 2249c411c3a1..410a4ffad98e 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -215,6 +215,8 @@ struct snd_usb_platform_ops { #if IS_ENABLED(CONFIG_SND_USB_AUDIO) int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops); int snd_usb_unregister_platform_ops(void); +struct snd_usb_stream *snd_usb_find_suppported_substream(int card_idx, + struct snd_pcm_hw_params *params, int direction); #else int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops) { @@ -225,5 +227,11 @@ int snd_usb_unregister_platform_ops(void) { return -EOPNOTSUPP; } + +struct snd_usb_stream *snd_usb_find_suppported_substream(int card_idx, + struct snd_pcm_hw_params *params, int direction) +{ + return NULL; +} #endif /* IS_ENABLED(CONFIG_SND_USB_AUDIO) */ #endif /* __USBAUDIO_CARD_H */ From patchwork Thu Jan 26 03:14:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48467 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69383wrn; Wed, 25 Jan 2023 19:16:31 -0800 (PST) X-Google-Smtp-Source: AMrXdXsEGTzL2pD6g+Gx0wvSltNR48J23Y2iwKi6vux+5ad8E5StnJRyjX9Ur/K2mB1PEmdrQXWI X-Received: by 2002:a05:6a20:d399:b0:ad:efda:5e5d with SMTP id iq25-20020a056a20d39900b000adefda5e5dmr38702298pzb.61.1674702991097; Wed, 25 Jan 2023 19:16:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702991; cv=none; d=google.com; s=arc-20160816; b=ywCRPUPB4My9BedFdqs4PMqzad45oV8WNB0BzVGg19aMmJAzvWvx6krebM6bI8L56W JuNhpAjupawCDxE1kHqaMBaPPL79eXHwJxs3Zy36EDPJBluCf1IQQx7W4icsZMaupBXF 7VA5LJOxDLWZcewBJ7ymD7QJUbau9amhfgUfgvbNjARhYrU+HvVrwR22jrLucwU9mNnS kk8Xl8GW+dm3ktGiTAfO8v29NrZNXlF8iMwppeaFaeo/gfZZEPQiZTsklT7SGwEeAKCX EjDNB4Mp7drC8Bqap7YByvr8PRc0uCLUEm7QOrMkOONfKVqWBYKIlTPITDinTCbWs4Sk Se7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=9YaFd6y9j4FenaXuzXxC96Owf6Vaq4DV+FD8SKInc2E=; b=U2i3HCYXqK0lGOi5eczDqTWV6vPde+ft/Lsly2D7cVu8u3T/Phv3BpZFPDZTqQNWUJ 0FAVFXi5ZXhGgefo5sZxwN+87MefPU33D+kbtiQOYel+BtNR9ZrR6t8EgjdX9c0ucntC BPqkJd0vKoT4n/Dh71/sUCTBJLL9pNUFMkzf7KXe2xmz/aRQxdxLzpwuBiwVLsD9Cak/ celtHycCezuAPqux6vfq6bXVIv0/R5lFxVh/sGZDGDRYxolX7yV363UQqq0RxMT38jiA PLq1uJlVV93Dm2KDOGaKfzdC1P2FRDQHGkxtG9inXZwdknvxo2XLA9PRQWugy+VTueIV LMqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=d1wXSEP4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v6-20020a63b646000000b004cd1e132878si7611984pgt.764.2023.01.25.19.16.16; Wed, 25 Jan 2023 19:16:31 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=d1wXSEP4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236197AbjAZDPq (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235965AbjAZDPk (ORCPT ); Wed, 25 Jan 2023 22:15:40 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 943F565F02; Wed, 25 Jan 2023 19:15:09 -0800 (PST) Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q3EgC7003775; Thu, 26 Jan 2023 03:14:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=9YaFd6y9j4FenaXuzXxC96Owf6Vaq4DV+FD8SKInc2E=; b=d1wXSEP48u2e5+zzWUFAmu/ckZ9QGtC7wPZa507gF+NIOhW0nXfCmNR1NBdIpMRBjkcF mEWkAoiMSlTmLMjbzeEDtctfaKPbt+k04KSEmgxPkLxFrhHSGrWaCnrgHXCxKe8e07bb Cp8X0YYee6L8tc+5oMTFdpXRtVTof3hHhvJ0UXJeSQahR2xQiMxx8FHrrywbL/IP7Imr oK420ht1ENPxCustA4XzCZhfxCpsLsDytftELPZvBLm6iIUiIRW07/z6cgtm9v8EqtHZ ohDzShXPfxhH1fRvjVqjOBTUJIJN+ugdhEQ4cElLpTybEldOsESlki5G0cg8nM+9IavD lQ== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nbd7arbma-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:49 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3En9T031339 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:49 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:48 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 18/22] sound: soc: soc-usb: Add PCM format check API for USB backend Date: Wed, 25 Jan 2023 19:14:20 -0800 Message-ID: <20230126031424.14582-19-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: t8Rm8HeS8Pc2SnXg9o-kF6dCC6jY6ZmE X-Proofpoint-GUID: t8Rm8HeS8Pc2SnXg9o-kF6dCC6jY6ZmE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 impostorscore=0 adultscore=0 clxscore=1015 priorityscore=1501 phishscore=0 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053363421925533?= X-GMAIL-MSGID: =?utf-8?q?1756053363421925533?= Introduce a check for 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. Signed-off-by: Wesley Cheng --- include/sound/soc-usb.h | 3 +++ sound/soc/soc-usb.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/sound/soc-usb.h b/include/sound/soc-usb.h index ec422a8a834f..d6a0a1bd9c60 100644 --- a/include/sound/soc-usb.h +++ b/include/sound/soc-usb.h @@ -21,6 +21,9 @@ struct snd_soc_usb { void *priv_data; }; +int snd_soc_usb_find_format(int card_idx, struct snd_pcm_hw_params *params, + int direction); + int snd_soc_usb_connect(struct device *usbdev, int card_idx); int snd_soc_usb_disconnect(struct device *usbdev); void snd_soc_usb_set_priv_data(struct device *dev, void *priv); diff --git a/sound/soc/soc-usb.c b/sound/soc/soc-usb.c index bfce6c9609e1..130cf12505f3 100644 --- a/sound/soc/soc-usb.c +++ b/sound/soc/soc-usb.c @@ -94,6 +94,19 @@ void snd_soc_usb_set_priv_data(struct device *dev, void *priv) } EXPORT_SYMBOL_GPL(snd_soc_usb_set_priv_data); +int snd_soc_usb_find_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_format); + /** * snd_soc_usb_add_port() - Add a USB backend port * @dev: USB backend device From patchwork Thu Jan 26 03:14:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48464 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69261wrn; Wed, 25 Jan 2023 19:16:02 -0800 (PST) X-Google-Smtp-Source: AMrXdXvq3qUmLOSKaNqCw3ZRVtKdddDfj3+S8EgLRfnWapN3KpVqnT7b93FQWZqPJhXlAnd3g2pb X-Received: by 2002:a05:6a20:45b:b0:b9:5fc4:6e3b with SMTP id b27-20020a056a20045b00b000b95fc46e3bmr22475987pzb.34.1674702962687; Wed, 25 Jan 2023 19:16:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702962; cv=none; d=google.com; s=arc-20160816; b=EnEyCRqRo67Z4jljQqvAVOMh2e177KHQc8bRYayKMGrVAjcr/D61ptNrbZjg2jnOxC LTh7v7LeugAuC61UMp3wyR4YOqFYDey4WmBh3LW86ptk7inNPY7DL6RUxF7SnD+PqHy6 DBQVph6LcwSXtRiaH7wuM7xGkMc6F/wO4yl2bheEgzyfc/wmD+K8fV1z/RHCcVcPIPDX TJEHwsIA1VvzZLNdsz54ne9JDArVfj1BxtzVHIpWDWpMzSLqD0rSvz9TSbirFIdt4PQc oiMD3SGS/WEJuFCNHLB19D+8okvYOQE0JQA0g320zAyi3xgM89UKg+srA0+FKeVMMZ4d 1aXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=1txMaotSHPsWFowBJzGiwKSG1+X0+lF7DacLGIuLInw=; b=RbUC3wsnhg+MGc5dK4wx+HuTtniuyrEoflPyxob1qC5mDvZ2VV6CiFTNmiZuY993rb 0uMllbkJDjskq3kMBekb7HORaFUaNv8wwGBwmlFvHDNgsP5qnpNHzO3CV7lR5ZPZN5Yp pnsHw7zMo4Vr1x/jeuHHJLVDvWSCvxGI2uvPXPxg/qNYQgNOfNlkmuLBIw0ehaV8a2sS P6nfgMzafrLvMcwieoi8s+GrmnUA01uethWCQREa8vclGt3K7y74v3rc1/xPOFRRsr0H LJ9hh3/QWa74u9QMwpF8dltnQDbiiKwiikHHH9o2kQiM2GxCF8TjzI7QQ6nIsKRGKbzA UjWg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=E9ULC8nn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x16-20020a170902b41000b0019441960a48si298830plr.236.2023.01.25.19.15.50; Wed, 25 Jan 2023 19:16:02 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=E9ULC8nn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236223AbjAZDPK (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236127AbjAZDOv (ORCPT ); Wed, 25 Jan 2023 22:14:51 -0500 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B992C65F02; Wed, 25 Jan 2023 19:14:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702889; x=1706238889; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=1txMaotSHPsWFowBJzGiwKSG1+X0+lF7DacLGIuLInw=; b=E9ULC8nn52pZyjtxobWzWw+vcC2MeLL+lRTwvjFJI0+jHTO9hyko6VWx KOOthXXlpXJDZ3IveJ0yMI3C/YMgqcBkjhXVYNiGwiiS9KWQRaJJPgqSH 6rgp5+QRy/9/0MVaDOmWJD5Ggr5yRsTnDl5tonJjGycIPD6ws6fHJMTou 0=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-02.qualcomm.com with ESMTP; 25 Jan 2023 19:14:49 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:49 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:48 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 19/22] sound: soc: qcom: qusb6: Ensure PCM format is supported by USB audio device Date: Wed, 25 Jan 2023 19:14:21 -0800 Message-ID: <20230126031424.14582-20-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053333630295550?= X-GMAIL-MSGID: =?utf-8?q?1756053333630295550?= 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 --- sound/soc/qcom/qdsp6/q6usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index afbff66108bc..0d3693c967ac 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -42,7 +42,10 @@ static int q6usb_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - return 0; + struct q6usb_port_data *data = dev_get_drvdata(dai->dev); + int direction = substream->stream; + + return snd_soc_usb_find_format(data->active_idx, params, direction); } static const struct snd_soc_dai_ops q6usb_ops = { .hw_params = q6usb_hw_params, From patchwork Thu Jan 26 03:14:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48481 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp74923wrn; Wed, 25 Jan 2023 19:35:05 -0800 (PST) X-Google-Smtp-Source: AK7set9rJT+gpo7Kb2n5MB7ZhRyW1LAGHXLXI9GTO39dm8CE6dkifLu2nlbBg7k5k8GvjT0n50dP X-Received: by 2002:a17:906:1e92:b0:878:4cc9:18a8 with SMTP id e18-20020a1709061e9200b008784cc918a8mr1916596ejj.29.1674704105475; Wed, 25 Jan 2023 19:35:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674704105; cv=none; d=google.com; s=arc-20160816; b=mNuUo3/sphNAWvHk3WhSOxeb5zPgpXKY+XLLLqZY17w8HVV8PO//8l76iJ0poxJ7TV NcFUI/qDlHnlkNmeYl5FCeyTBm5/VFCZd0Cls7jh/vDIsV4nCVHqzuqMWnZJ0251fEnL 5RGLGahWtC9qRTWKJMl3JE0ymCXIOxrjUCq4T9E74+xeb2xXxd9l6dItUyV/fVvj6r7o oG3pAU0XFc9i3DDbqdZOcDNBbN6mRsqeJGSakaFtq/SEoKJLXkziwqj9efnzJQgna+Vr soqAARUP074WY8z94Yp79wlUOCil+9xCECusTMa5PrqCvFSeyU4ECJLF3PszmNQCHcDy 81Ow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=uk5UGMqs/ei1kDHwf+Z178yIlngwmaPizli7rDmuuVo=; b=dCdEEYOXSCyl2+F2ANy6wMEgVGzCwj1ma+SieaIIKSUVV8V1k72QJQ3fRshoSVUHNK wAhbNBqCDeqsRTxBLT3UKqcwQymzpCz8GkfS3+e4xhhl6xdRSZI/H3d4yvDSCAvN7sxp MY9EU2VVWb77PbB11EaBM69/ZuGqnXEovTL2ZqjWlwm+M7q5yQ6+RwgH6481MRfXfhiC iTsineXK2C1vc2E3OzupMBbO7q1ki3T2ElobVPClz6jOXfOCAP8tD/wT7s4Vy4yCzqNJ ETZv8xBvm1/vj4Gghegxqks80PAZmEK6XiLxrBittZwVvjgWQIAz2ydJwBXvmjCbZMIF 26ew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=dMm7C3Yg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id wl14-20020a170907310e00b00871a4e8d7bdsi7473973ejb.1009.2023.01.25.19.34.38; Wed, 25 Jan 2023 19:35:05 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=dMm7C3Yg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236266AbjAZD0e (ORCPT + 99 others); Wed, 25 Jan 2023 22:26:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229481AbjAZD0d (ORCPT ); Wed, 25 Jan 2023 22:26:33 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E43599D; Wed, 25 Jan 2023 19:26:32 -0800 (PST) Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30Q32xNn004834; Thu, 26 Jan 2023 03:14:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=uk5UGMqs/ei1kDHwf+Z178yIlngwmaPizli7rDmuuVo=; b=dMm7C3Yg4rMZfpZ5dyB37WaG6RY1RtWh0frAKZjsL4n/U+4R9Yy/j/khISLZ0LbiI5A3 xrKS+bSTexJk1ZUhRdqw9jdCy4mfp8ONw0zmOiZyye1Bxoj/d0PipdiU4GdEpEbG0DJJ iGUvOb3C2MrkrynJgiXYVcBd0DOvfcJHkxSUkUefjgNrvozV7gkB358QIUvSUOFmgIrN vFjZf+dSF42mqAFOJu4xCHcFQ+lRtN2ZOC8JQ0RqEXg81mHEIJA1B6hAZ7TWRXCHEg6n B4q5R03hDMtU0wlowlECnCVeK//aH2OExU4A45vF+fY3dwlIDz/LBhucZDFQ6Lg95Le1 3w== Received: from nasanppmta01.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nbd7arbmb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:50 +0000 Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 30Q3EopC008329 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 03:14:50 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:49 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 20/22] sound: usb: Prevent starting of audio stream if in use Date: Wed, 25 Jan 2023 19:14:22 -0800 Message-ID: <20230126031424.14582-21-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: CNJn2OyEhsGz6hbWYzCWCNzTbT0Ll6uu X-Proofpoint-GUID: CNJn2OyEhsGz6hbWYzCWCNzTbT0Ll6uu X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-25_14,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 spamscore=0 mlxlogscore=898 impostorscore=0 adultscore=0 clxscore=1015 priorityscore=1501 phishscore=0 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260028 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756054531754515300?= X-GMAIL-MSGID: =?utf-8?q?1756054531754515300?= With USB audio offloading, an audio session is started from the ASoC platform sound card and PCM devices. Likewise, the USB SND path is still readily available for use, in case the non-offload path is desired. In order to prevent the two entities from attempting to use the USB bus, introduce a flag that determines when either paths are in use. If a PCM device is already in use, the check will return an error to userspace notifying that the stream is currently busy. This ensures that only one path is using the USB substream. Signed-off-by: Wesley Cheng --- sound/usb/card.h | 1 + sound/usb/pcm.c | 19 +++++++++++++++++-- sound/usb/qcom/qc_audio_offload.c | 15 ++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 410a4ffad98e..ff6d4695e727 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -163,6 +163,7 @@ struct snd_usb_substream { unsigned int pkt_offset_adj; /* Bytes to drop from beginning of packets (for non-compliant devices) */ unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */ + unsigned int opened:1; /* pcm device opened */ unsigned int running: 1; /* running status */ unsigned int period_elapsed_pending; /* delay period handling */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0b01a5dfcb73..8946f8ddb892 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1114,8 +1114,15 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = &as->substream[direction]; + struct snd_usb_audio *chip = subs->stream->chip; int ret; + mutex_lock(&chip->mutex); + if (subs->opened) { + mutex_unlock(&chip->mutex); + return -EBUSY; + } + runtime->hw = snd_usb_hardware; /* need an explicit sync to catch applptr update in low-latency mode */ if (direction == SNDRV_PCM_STREAM_PLAYBACK && @@ -1132,13 +1139,17 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) ret = setup_hw_info(runtime, subs); if (ret < 0) - return ret; + goto out; ret = snd_usb_autoresume(subs->stream->chip); if (ret < 0) - return ret; + goto out; ret = snd_media_stream_init(subs, as->pcm, direction); if (ret < 0) snd_usb_autosuspend(subs->stream->chip); + subs->opened = 1; +out: + mutex_unlock(&chip->mutex); + return ret; } @@ -1147,6 +1158,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) int direction = substream->stream; struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; + struct snd_usb_audio *chip = subs->stream->chip; int ret; snd_media_stop_pipeline(subs); @@ -1160,6 +1172,9 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) subs->pcm_substream = NULL; snd_usb_autosuspend(subs->stream->chip); + mutex_lock(&chip->mutex); + subs->opened = 0; + mutex_unlock(&chip->mutex); return 0; } diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index c1254d5f680d..9bd09282e70d 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1365,12 +1365,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, @@ -1392,6 +1397,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) { @@ -1413,6 +1423,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 26 03:14:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48465 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69308wrn; Wed, 25 Jan 2023 19:16:12 -0800 (PST) X-Google-Smtp-Source: AMrXdXv+46fPvvsXBF/U1EhhzIhAwWS4j+lNSEZd/STtvK/EiVjwcqGaPEfXAKau2fOllvJY3UEu X-Received: by 2002:a05:6a20:4407:b0:b8:525f:555f with SMTP id ce7-20020a056a20440700b000b8525f555fmr49965080pzb.53.1674702972407; Wed, 25 Jan 2023 19:16:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674702972; cv=none; d=google.com; s=arc-20160816; b=c2EnTP8xlVqvbGDnWR3MG0wwYgdzs5L2mv2JGMkCGv3KWKYTpFC+o7vdokJjfS7nmn bScL2rf+w1BCnB+yM9RQrgHy6uZDBBe6z5Yw9vlVwNTNkFfZ/5lMx5CkKPH7V169iS2w VhOD2PB9k+fAGWRWt5EHmezHWyRhL9Q/ethBADQa/QjRe8RSgVIXX52JVy5p25EqHudI yT55kRFJRIo2Z5b0W+fc2tQ/RLssK4h4JjiFlLWxjDsnPJbx6whLdwF33oEES60ZN0wI vtd6+/GnEO6mm2i1k0pqHopd8UQao0QWAqzERksDorgiffagF6xv9xVYixLBRZeenVmJ 9qHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=yGFwuojaQ5ML4dsz23/al/799O12g89UeuaQci4f9LM=; b=aT4RW4RzJ0wuYZ/cMHi/fAFkB6gZ9EzXhiSPyX3l1Cv7ASH29BHCoF1dNMVi5O82Jq afn2UjRKjPnhaD3d/PLD9sK5Y1ZdvsOeVBgNrDo51oW2njg7TpQgGBqEwjzfcg6isKKZ MUeGXKDAcO4DN21nmPKxST6hDhIR0ix55p+lVKfIr98cnsxmk0xpILx0p9QT20p9Kxb7 CnHjsULJdpMnwcqgq7AKCe+3LYJlmTz9YtchVrPL9EowR7BneYhsMtfKMpVUIHwGBRBV IeSnTJQsqa3A4MaXFC2nm/wndKIvqRuz8ngOMp+o1v24xQLjdRjR32GORPMtz5D8dCH4 Ls4Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=lhcMoYT3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j191-20020a6380c8000000b004deafa8f3b3si7343pgd.739.2023.01.25.19.16.00; Wed, 25 Jan 2023 19:16:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=lhcMoYT3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236182AbjAZDPP (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44734 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236156AbjAZDO5 (ORCPT ); Wed, 25 Jan 2023 22:14:57 -0500 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 16B8865EF5; Wed, 25 Jan 2023 19:14:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702891; x=1706238891; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=yGFwuojaQ5ML4dsz23/al/799O12g89UeuaQci4f9LM=; b=lhcMoYT3uo0e0XuZyVNr7Q3whei7ZHcPMjlASdqmCw09zDoSVCZI4IqK zqSubjlucP9E2qZb07G6N4Vod18LJ4/6AHcptfY8ctlhjUsz865lS/r2P SjMvXMK2jP2ff/RlFbAX5Zta7pcXf8x633+ND73nFMGM67JfU0WQPqhKl Y=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-02.qualcomm.com with ESMTP; 25 Jan 2023 19:14:50 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:50 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:50 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 21/22] ASoC: dt-bindings: Add Q6USB backend bindings Date: Wed, 25 Jan 2023 19:14:23 -0800 Message-ID: <20230126031424.14582-22-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053343564194994?= X-GMAIL-MSGID: =?utf-8?q?1756053343564194994?= Add a dt-binding to describe the definition of enabling the Q6 USB backend device for audio offloading. The node carries information, which is passed along to the QC USB SND class driver counterpart. These parameters will be utilized during QMI stream enable requests. Signed-off-by: Wesley Cheng --- .../bindings/sound/qcom,q6usb-dais.yaml | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6usb-dais.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,q6usb-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6usb-dais.yaml new file mode 100644 index 000000000000..e24b4d52fa7e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,q6usb-dais.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,q6usb-dais.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm ASoC USB backend DAI + +maintainers: + - Wesley Cheng + +description: + The Q6USB backend is a supported AFE port on the Q6DSP. This backend + driver will communicate the required settings to the QC USB SND class + driver for properly enabling the audio stream. Parameters defined + under this node will carry settings, which will be passed along during + the QMI stream enable request. + +properties: + compatible: + enum: + - qcom,q6usb-dais + + iommus: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + qcom,usb-audio-stream-id: + description: + SID for the Q6DSP processor for IOMMU mapping. + $ref: /schemas/types.yaml#/definitions/uint32 + + qcom,usb-audio-intr-num: + description: + Desired XHCI interrupter number to use. + $ref: /schemas/types.yaml#/definitions/uint32 + +required: + - compatible + - '#sound-dai-cells' + - qcom,usb-audio-intr-num + +additionalProperties: false + +examples: + - | + usbdai: usbd { + compatible = "qcom,q6usb-dais"; + #sound-dai-cells = <1>; + iommus = <&apps_smmu 0x180f 0x0>; + qcom,usb-audio-stream-id = <0xf>; + qcom,usb-audio-intr-num = <2>; + }; From patchwork Thu Jan 26 03:14:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 48470 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp69575wrn; Wed, 25 Jan 2023 19:17:08 -0800 (PST) X-Google-Smtp-Source: AMrXdXvnCn5v8ODDaHeJN3/tqYSUhvNIgfhjHVjfvqm8txkbCQMgU5I+hhOFYM2iLjst17PWwJp7 X-Received: by 2002:a17:903:31c9:b0:194:7ce2:aa5e with SMTP id v9-20020a17090331c900b001947ce2aa5emr30744326ple.28.1674703027990; Wed, 25 Jan 2023 19:17:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674703027; cv=none; d=google.com; s=arc-20160816; b=fPNFUK1PN5T+vAxv1Hn8LO+eZLSrz2ndmqUKC5iepUZzyAtl5/P2aNJs0bCqqK6Zql 15936NLcrDmN+VarMQZzaULLv3EY4E95U63QdFnsDgmEClatqU9afCIJmL4J6kEvvR6F jmXHbLAVSf9F+oEYahfCtXtVM6wjdG8MX7vYB4We/3vMvTfTYnV7NdTza/W96V28ykFY wvw8cRcNP43tXJNgxpn3LX77hZc1x+7uwal96OIT8c1hrWVc7reCMIOK/B+jE092LsEM yTxfzQzO3H8QeTGeyvoPxR5QXnBI1qqg+E/i6Zrb3S5TlpTegWG1rpfQr737lN7kGmRf rqqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=l+njOKa/UFfOWF7VK5VgFL97OAxm3R4PP9cElfezPbw=; b=k+0yhwd/RhspMCIkLv0oqyf12/Bv3Ox3pDVuNMAAgjXMeUnNDAV447K8mBY7Fm+oTB 1Fey+JkuOs9Kt8gw/59XMPUoAO0TS6uL0ZMPLJsbN9o3jyvxRab3uUrrLFpcJKLI8/R5 TCD9vaJTyf1d9w5R2kGDUmh2lf8nasdIIFsy6o+eItDIcLnbo6BvvC3JMri8Y/+HYn7w WCrVorBVi/24+GiLRZaIddiWTGuIzSSU/cDbF0YxVRFjZOAS/xRftxSL3aqpypbfTljF Xd0dqt0LXUgaWYQpbQ0+QtraohLWAeBJUG5iy1ikGJue0N3TVehsAntxWUYCkhc24ICi TK/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=vB6UxmmK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id e2-20020a17090301c200b00193373e40afsi384567plh.172.2023.01.25.19.16.55; Wed, 25 Jan 2023 19:17:07 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=vB6UxmmK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236273AbjAZDPU (ORCPT + 99 others); Wed, 25 Jan 2023 22:15:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236179AbjAZDPJ (ORCPT ); Wed, 25 Jan 2023 22:15:09 -0500 Received: from alexa-out-sd-01.qualcomm.com (alexa-out-sd-01.qualcomm.com [199.106.114.38]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3AF065EEE; Wed, 25 Jan 2023 19:14:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1674702891; x=1706238891; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=l+njOKa/UFfOWF7VK5VgFL97OAxm3R4PP9cElfezPbw=; b=vB6UxmmKJiidhvUvgYIC/2kTD/PNXtPvhVkcsgLm/K0Sa0hMY1OHHlct 0Y7kE0CQqnUcdVIel9mf1DDcqsYbiv9xfxtR2sBLNGGtg7T2RRVtcq082 A7lidPtLEzCeMjW3koVyR6ghxsw2orY6Pv6W8mCL5AaTQHRTWteBuAh1s 8=; Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-01.qualcomm.com with ESMTP; 25 Jan 2023 19:14:51 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg-SD-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2023 19:14:51 -0800 Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 25 Jan 2023 19:14:50 -0800 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [RFC PATCH v2 22/22] ASoC: dt-bindings: Update example for enabling USB offload on SM8250 Date: Wed, 25 Jan 2023 19:14:24 -0800 Message-ID: <20230126031424.14582-23-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230126031424.14582-1-quic_wcheng@quicinc.com> References: <20230126031424.14582-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nasanex01c.na.qualcomm.com (10.45.79.139) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756053402134857906?= X-GMAIL-MSGID: =?utf-8?q?1756053402134857906?= Add an example on enabling of USB offload for the Q6DSP. The routing can be done by the mixer, which can pass the multimedia stream to the USB backend. Signed-off-by: Wesley Cheng --- .../devicetree/bindings/sound/qcom,sm8250.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 70080d04ddc9..60cd84e6727a 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -216,6 +216,19 @@ examples: sound-dai = <&vamacro 0>; }; }; + + usb-dai-link { + link-name = "USB Playback"; + cpu { + sound-dai = <&q6afedai USB_RX>; + }; + codec { + sound-dai = <&usbdai USB_RX>; + }; + platform { + sound-dai = <&q6routing>; + }; + }; }; - |