From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94D71C38159 for ; Wed, 18 Jan 2023 16:11:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231140AbjARQKE (ORCPT ); Wed, 18 Jan 2023 11:10:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230373AbjARQJF (ORCPT ); Wed, 18 Jan 2023 11:09:05 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0D7145890 for ; Wed, 18 Jan 2023 08:05:16 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgr6022836; Wed, 18 Jan 2023 10:05:00 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=RrsmUAoPfdKz/GjTW3d2CI1v1QDtyYNp4XQoW8Gfmu4=; b=lQ6o62LkRIncspk6CTo7TCqKVATdDk0oiVuVG99ajX5AaiO7NHtPCwg18mLY3uvS/JWz OySbtAXgH06LDTOeOAKEJBtBQedcZjuznz4efhO+7VPUxrgAoI9NSwQdFQsQMvup1dSA mg4YVy+JdkfSRh6KPARNEP9taMBjss5FqzDc5cwBC44ao/fVldacntdSGBRa3anaXN7B qt0EjydzzJOL7SWD/VN1jfXDpBmdmRRPwzFTLp107EAsU2ExQ5KZQ+JKZ5hrGUB2e4ul 7EdoSPriJUxlvLjYRJrtOoNuUjhC9EFZrvoMqLYus4Hd3dgNrQ4BlJPgVT1UW742HKkg Vw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:00 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:57 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.7 via Frontend Transport; Wed, 18 Jan 2023 10:04:57 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 0BA1EB12; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Stefan Binding Subject: [PATCH v2 1/8] soundwire: stream: Add specific prep/deprep commands to port_prep callback Date: Wed, 18 Jan 2023 16:04:45 +0000 Message-ID: <20230118160452.2385494-2-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: -czQAVRU0DdhMIyzE7Xe7chznsaOXhYp X-Proofpoint-ORIG-GUID: -czQAVRU0DdhMIyzE7Xe7chznsaOXhYp X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Currently, port_prep callback only has commands for PRE_PREP, PREP, and POST_PREP, which doesn't directly say whether this is for a prepare or deprepare call. Extend the command list enum to say whether the call is for prepare or deprepare aswell. Also remove SDW_OPS_PORT_PREP from sdw_port_prep_ops as this is unused, and update this enum to be simpler and more consistent with enum sdw_clk_stop_type. Note: Currently, the only users of SDW_OPS_PORT_POST_PREP are codec drivers sound/soc/codecs/wsa881x.c and sound/soc/codecs/wsa883x.c, both of which seem to assume that POST_PREP only occurs after a prepare, even though it would also have occurred after a deprepare. Since it doesn't make sense to mark the port prepared after a deprepare, changing the enum to separate PORT_DEPREP from PORT_PREP should make the check for PORT_PREP in those drivers be more logical. Signed-off-by: Stefan Binding Reviewed-by: Pierre-Louis Bossart --- drivers/soundwire/stream.c | 4 ++-- include/linux/soundwire/sdw.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index df3b36670df4c..1652fb5737d9d 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -469,7 +469,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *= bus, } =20 /* Inform slave about the impending port prepare */ - sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_PRE_PREP); + sdw_do_port_prep(s_rt, prep_ch, prep ? SDW_OPS_PORT_PRE_PREP : SDW_OPS_PO= RT_PRE_DEPREP); =20 /* Prepare Slave port implementing CP_SM */ if (!dpn_prop->simple_ch_prep_sm) { @@ -501,7 +501,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *= bus, } =20 /* Inform slaves about ports prepared */ - sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_POST_PREP); + sdw_do_port_prep(s_rt, prep_ch, prep ? SDW_OPS_PORT_POST_PREP : SDW_OPS_P= ORT_POST_DEPREP); =20 /* Disable interrupt after Port de-prepare */ if (!prep && intr) diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 3cd2a761911ff..547fc1b30a51a 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -569,13 +569,15 @@ struct sdw_prepare_ch { * enum sdw_port_prep_ops: Prepare operations for Data Port * * @SDW_OPS_PORT_PRE_PREP: Pre prepare operation for the Port - * @SDW_OPS_PORT_PREP: Prepare operation for the Port + * @SDW_OPS_PORT_PRE_DEPREP: Pre deprepare operation for the Port * @SDW_OPS_PORT_POST_PREP: Post prepare operation for the Port + * @SDW_OPS_PORT_POST_DEPREP: Post deprepare operation for the Port */ enum sdw_port_prep_ops { SDW_OPS_PORT_PRE_PREP =3D 0, - SDW_OPS_PORT_PREP =3D 1, - SDW_OPS_PORT_POST_PREP =3D 2, + SDW_OPS_PORT_PRE_DEPREP, + SDW_OPS_PORT_POST_PREP, + SDW_OPS_PORT_POST_DEPREP, }; =20 /** --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34CF0C677F1 for ; Wed, 18 Jan 2023 16:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231410AbjARQKR (ORCPT ); Wed, 18 Jan 2023 11:10:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230420AbjARQJF (ORCPT ); Wed, 18 Jan 2023 11:09:05 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3225E46171 for ; Wed, 18 Jan 2023 08:05:17 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgr7022836; Wed, 18 Jan 2023 10:05:03 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=k5oNoCYjcpl/Ta/zXWc2NtstMbInyOsQe4rw1amTQII=; b=VC3KI2qdVhc8l7oQFesA70bP5axv+8ui/dmgewZfaLSUVEqMTiruqc61OGcHzU4+HGkv SHRW9mlYjCMd9TlquQ+MnP8Uenel5lJLQM7rlQX8fPmjp3rXsP+kYyxgg4Gy42fu6dk7 J5u/KR2Xb+WTr3LK+PNBfH4ZWq9MAQ/gdUl1p/ci0gS9b+ebcNiJFDaFlznQMvcJY9oM smt/ZMgUVlExDpNh7IthYR3ZU4AeUAo1PKVqJG0+p7ZXSt+crJUkwFLZb0yRXx9sbnDO B7SHBJsxkbdTf8gpRHT5Vpo0HA04axh/llBJVQmNVUCWzSF9X43CQXn0J9XSAf/JGNnD lQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:02 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:57 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.21 via Frontend Transport; Wed, 18 Jan 2023 10:04:57 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 2A39F11CC; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 2/8] ASoC: cs42l42: Add SOFT_RESET_REBOOT register Date: Wed, 18 Jan 2023 16:04:46 +0000 Message-ID: <20230118160452.2385494-3-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: Qs0q9NiF4zbq3I7Fi1ZM13SbCK8xRqKM X-Proofpoint-ORIG-GUID: Qs0q9NiF4zbq3I7Fi1ZM13SbCK8xRqKM X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald The SOFT_RESET_REBOOT register is needed to recover CS42L42 state after a Soundwire bus reset. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding --- include/sound/cs42l42.h | 5 +++++ sound/soc/codecs/cs42l42.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/include/sound/cs42l42.h b/include/sound/cs42l42.h index 1d1c24fdd0cae..3994e933db195 100644 --- a/include/sound/cs42l42.h +++ b/include/sound/cs42l42.h @@ -34,6 +34,7 @@ #define CS42L42_PAGE_24 0x2400 #define CS42L42_PAGE_25 0x2500 #define CS42L42_PAGE_26 0x2600 +#define CS42L42_PAGE_27 0x2700 #define CS42L42_PAGE_28 0x2800 #define CS42L42_PAGE_29 0x2900 #define CS42L42_PAGE_2A 0x2A00 @@ -720,6 +721,10 @@ =20 #define CS42L42_SRC_SDOUT_FS (CS42L42_PAGE_26 + 0x09) =20 +/* Page 0x27 DMA */ +#define CS42L42_SOFT_RESET_REBOOT (CS42L42_PAGE_27 + 0x01) +#define CS42L42_SFT_RST_REBOOT_MASK BIT(1) + /* Page 0x28 S/PDIF Registers */ #define CS42L42_SPDIF_CTL1 (CS42L42_PAGE_28 + 0x01) #define CS42L42_SPDIF_CTL2 (CS42L42_PAGE_28 + 0x02) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 2fefbcf7bd130..82aa11d6937be 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -293,6 +293,7 @@ bool cs42l42_readable_register(struct device *dev, unsi= gned int reg) case CS42L42_SPDIF_SW_CTL1: case CS42L42_SRC_SDIN_FS: case CS42L42_SRC_SDOUT_FS: + case CS42L42_SOFT_RESET_REBOOT: case CS42L42_SPDIF_CTL1: case CS42L42_SPDIF_CTL2: case CS42L42_SPDIF_CTL3: @@ -358,6 +359,7 @@ bool cs42l42_volatile_register(struct device *dev, unsi= gned int reg) case CS42L42_LOAD_DET_DONE: case CS42L42_DET_STATUS1: case CS42L42_DET_STATUS2: + case CS42L42_SOFT_RESET_REBOOT: return true; default: return false; --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5FD95C678D4 for ; Wed, 18 Jan 2023 16:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231506AbjARQK5 (ORCPT ); Wed, 18 Jan 2023 11:10:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41570 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229572AbjARQJS (ORCPT ); Wed, 18 Jan 2023 11:09:18 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70A5C4743F for ; Wed, 18 Jan 2023 08:05:19 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgr8022836; Wed, 18 Jan 2023 10:05:04 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=7baE4YHbXVUPM74pWQRBjY+48Wfg+BcP2GKd/5ZVfB8=; b=AedMLsmZGu95xNC4tHAZEfFWQPFq9/UWQ94EiLMkHucSZbKwBc0kdHu2KxLYU1fSWBjf vzj6ZvVzB42q6uSW6z0ZdHtGldRsJ0pZjAHi8EvGpx1J1t9wokytw64rQBD926fsYt+s /NPhaGZiPUMH6ntHmFrclyq0rlWuMUEZO1P3aXqSUp71mKjG9VvL9nmEMeAXE65/vQ5F 049gZN2IyXiD/CXEg72f5ev3c9d6oXwj74J10Vo0K8j9+2RIlL6CbLINihjR3VE5Dxtl PqLdrs2QDfA2SZJf5zgJzULJ/MV6zaOgKlgWtsMYM6bMdCiwq3C7dFmBtN46O7f2/vj1 YA== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:04 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:57 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.21 via Frontend Transport; Wed, 18 Jan 2023 10:04:57 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 4DA1111CB; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 3/8] ASoC: cs42l42: Ensure MCLKint is a multiple of the sample rate Date: Wed, 18 Jan 2023 16:04:47 +0000 Message-ID: <20230118160452.2385494-4-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: seZ911bfDpOLQvm-3_xM2TJlVpv7ZKeH X-Proofpoint-ORIG-GUID: seZ911bfDpOLQvm-3_xM2TJlVpv7ZKeH X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald The chosen clocking configuration must give an internal MCLK (MCLKint) that is an integer multiple of the sample rate. On I2S each of the supported bit clock frequencies can only be generated from one sample rate group (either the 44100 or the 48000) so the code could use only the bitclock to look up a PLL config. The relationship between sample rate and bitclock frequency is more complex on Soundwire and so it is possible to set a frame shape to generate a bitclock from the "wrong" group. For example 2*147 with a 48000 sample rate would give a bitclock of 14112000 which on I2S could only be derived from a 44100 sample rate. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding Reviewed-by: Pierre-Louis Bossart --- sound/soc/codecs/cs42l42.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 82aa11d6937be..939f8bcc222c0 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -653,7 +653,8 @@ static const struct cs42l42_pll_params pll_ratio_table[= ] =3D { { 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1} }; =20 -static int cs42l42_pll_config(struct snd_soc_component *component, unsigne= d int clk) +static int cs42l42_pll_config(struct snd_soc_component *component, unsigne= d int clk, + unsigned int sample_rate) { struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); int i; @@ -668,6 +669,10 @@ static int cs42l42_pll_config(struct snd_soc_component= *component, unsigned int } =20 for (i =3D 0; i < ARRAY_SIZE(pll_ratio_table); i++) { + /* MCLKint must be a multiple of the sample rate */ + if (pll_ratio_table[i].mclk_int % sample_rate) + continue; + if (pll_ratio_table[i].sclk =3D=3D clk) { cs42l42->pll_config =3D i; =20 @@ -893,6 +898,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substre= am *substream, struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); unsigned int channels =3D params_channels(params); unsigned int width =3D (params_width(params) / 8) - 1; + unsigned int sample_rate =3D params_rate(params); unsigned int slot_width =3D 0; unsigned int val =3D 0; unsigned int bclk; @@ -956,11 +962,11 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_subst= ream *substream, break; } =20 - ret =3D cs42l42_pll_config(component, bclk); + ret =3D cs42l42_pll_config(component, bclk, sample_rate); if (ret) return ret; =20 - cs42l42_src_config(component, params_rate(params)); + cs42l42_src_config(component, sample_rate); =20 return 0; } --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2534CC38147 for ; Wed, 18 Jan 2023 16:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231321AbjARQKM (ORCPT ); Wed, 18 Jan 2023 11:10:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230424AbjARQJG (ORCPT ); Wed, 18 Jan 2023 11:09:06 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1645D47432 for ; Wed, 18 Jan 2023 08:05:19 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEEjlA023722; Wed, 18 Jan 2023 10:05:03 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=TTC47bgNB45idzSbfNOI1xh6OyXSxo6PonYazO3r2IQ=; b=HVG3RfRt9/sRcEmYkIYY0FFCi3Z2tAhh+vV8bgoC/S32GKGiIBTaYxJhWXTnjs31G4aE z7s0Z36WLmeDQbXU5ksNlxE1Tgv1dRrVAQvX+kFIFYwoR0TLWI3N3kFw2D2J3Y2XJ/CB Gx/EPnHFYfo/doylK2SFXMBVushbVDoSuXEg30/RF7subvCVYlTesaIXroMbh4ckIs6C 6UYPSpkEJKwVlUJxpENZ2V4b1wDo6xXRk4lOaVs1JzyfeK4MePzR21mArY7I21qK72z+ aVpJadUmHdxqQf9X6lKPphfCGgLAPo2fCHNsfYM51hmT1seL0+yE0JwxYC1i8dFwROVR TQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk8-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:02 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:57 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.21 via Frontend Transport; Wed, 18 Jan 2023 10:04:57 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 702B0B12; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 4/8] ASoC: cs42l42: Separate ASP config from PLL config Date: Wed, 18 Jan 2023 16:04:48 +0000 Message-ID: <20230118160452.2385494-5-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: 4pwKZYdmdN9L1uDQbYMxmLtOSsLXRyNt X-Proofpoint-ORIG-GUID: 4pwKZYdmdN9L1uDQbYMxmLtOSsLXRyNt X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald Setup of the ASP (audio serial port) was being done as a side-effect of cs42l42_pll_config() and forces a restriction on the ratio of sample_rate to bit_clock that is invalid for Soundwire. Move the ASP setup into a dedicated function. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding --- sound/soc/codecs/cs42l42.c | 81 +++++++++++++++++++++----------------- sound/soc/codecs/cs42l42.h | 1 - 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 939f8bcc222c0..d81c6eb1c1e59 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -658,7 +658,6 @@ static int cs42l42_pll_config(struct snd_soc_component = *component, unsigned int { struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); int i; - u32 fsync; =20 /* Don't reconfigure if there is an audio stream running */ if (cs42l42->stream_use) { @@ -684,40 +683,6 @@ static int cs42l42_pll_config(struct snd_soc_component= *component, unsigned int (pll_ratio_table[i].mclk_int !=3D 24000000)) << CS42L42_INTERNAL_FS_SHIFT); - - /* Set up the LRCLK */ - fsync =3D clk / cs42l42->srate; - if (((fsync * cs42l42->srate) !=3D clk) - || ((fsync % 2) !=3D 0)) { - dev_err(component->dev, - "Unsupported sclk %d/sample rate %d\n", - clk, - cs42l42->srate); - return -EINVAL; - } - /* Set the LRCLK period */ - snd_soc_component_update_bits(component, - CS42L42_FSYNC_P_LOWER, - CS42L42_FSYNC_PERIOD_MASK, - CS42L42_FRAC0_VAL(fsync - 1) << - CS42L42_FSYNC_PERIOD_SHIFT); - snd_soc_component_update_bits(component, - CS42L42_FSYNC_P_UPPER, - CS42L42_FSYNC_PERIOD_MASK, - CS42L42_FRAC1_VAL(fsync - 1) << - CS42L42_FSYNC_PERIOD_SHIFT); - /* Set the LRCLK to 50% duty cycle */ - fsync =3D fsync / 2; - snd_soc_component_update_bits(component, - CS42L42_FSYNC_PW_LOWER, - CS42L42_FSYNC_PULSE_WIDTH_MASK, - CS42L42_FRAC0_VAL(fsync - 1) << - CS42L42_FSYNC_PULSE_WIDTH_SHIFT); - snd_soc_component_update_bits(component, - CS42L42_FSYNC_PW_UPPER, - CS42L42_FSYNC_PULSE_WIDTH_MASK, - CS42L42_FRAC1_VAL(fsync - 1) << - CS42L42_FSYNC_PULSE_WIDTH_SHIFT); if (pll_ratio_table[i].mclk_src_sel =3D=3D 0) { /* Pass the clock straight through */ snd_soc_component_update_bits(component, @@ -809,6 +774,46 @@ static void cs42l42_src_config(struct snd_soc_componen= t *component, unsigned int fs << CS42L42_CLK_OASRC_SEL_SHIFT); } =20 +static int cs42l42_asp_config(struct snd_soc_component *component, + unsigned int sclk, unsigned int sample_rate) +{ + u32 fsync =3D sclk / sample_rate; + + /* Set up the LRCLK */ + if (((fsync * sample_rate) !=3D sclk) || ((fsync % 2) !=3D 0)) { + dev_err(component->dev, + "Unsupported sclk %d/sample rate %d\n", + sclk, + sample_rate); + return -EINVAL; + } + /* Set the LRCLK period */ + snd_soc_component_update_bits(component, + CS42L42_FSYNC_P_LOWER, + CS42L42_FSYNC_PERIOD_MASK, + CS42L42_FRAC0_VAL(fsync - 1) << + CS42L42_FSYNC_PERIOD_SHIFT); + snd_soc_component_update_bits(component, + CS42L42_FSYNC_P_UPPER, + CS42L42_FSYNC_PERIOD_MASK, + CS42L42_FRAC1_VAL(fsync - 1) << + CS42L42_FSYNC_PERIOD_SHIFT); + /* Set the LRCLK to 50% duty cycle */ + fsync =3D fsync / 2; + snd_soc_component_update_bits(component, + CS42L42_FSYNC_PW_LOWER, + CS42L42_FSYNC_PULSE_WIDTH_MASK, + CS42L42_FRAC0_VAL(fsync - 1) << + CS42L42_FSYNC_PULSE_WIDTH_SHIFT); + snd_soc_component_update_bits(component, + CS42L42_FSYNC_PW_UPPER, + CS42L42_FSYNC_PULSE_WIDTH_MASK, + CS42L42_FRAC1_VAL(fsync - 1) << + CS42L42_FSYNC_PULSE_WIDTH_SHIFT); + + return 0; +} + static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int= fmt) { struct snd_soc_component *component =3D codec_dai->component; @@ -904,8 +909,6 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substre= am *substream, unsigned int bclk; int ret; =20 - cs42l42->srate =3D params_rate(params); - if (cs42l42->bclk_ratio) { /* machine driver has set the BCLK/samp-rate ratio */ bclk =3D cs42l42->bclk_ratio * params_rate(params); @@ -966,6 +969,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substr= eam *substream, if (ret) return ret; =20 + ret =3D cs42l42_asp_config(component, bclk, sample_rate); + if (ret) + return ret; + cs42l42_src_config(component, sample_rate); =20 return 0; diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index a721366641127..17aab06adc8e6 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -36,7 +36,6 @@ struct cs42l42_private { int pll_config; u32 sclk; u32 bclk_ratio; - u32 srate; u8 plug_state; u8 hs_type; u8 ts_inv; --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6D47C32793 for ; Wed, 18 Jan 2023 16:11:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229666AbjARQLO (ORCPT ); Wed, 18 Jan 2023 11:11:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229829AbjARQJW (ORCPT ); Wed, 18 Jan 2023 11:09:22 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75981474E5 for ; Wed, 18 Jan 2023 08:05:19 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgr9022836; Wed, 18 Jan 2023 10:05:06 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=VkEQ/+6tCb28lQhqZZB7/1qdgbcRJIIlgjD9dLONQZg=; b=CfLnuovqxnPb5kq1igrKUZGiD5POleBH4VAYwmCW7HQWBFwDwFgWbFP7dykE4IkCaDZF +CBEPbLpzCtZwZCDKJLfSByVZSBXk0nZwgugkp1Qy86Ja21Rm+DtsG+7rt0JQA9tKF5v lmmx9Bk023eYIZymYn2rTjw648hPCYXzDRo1wdr4Kt85XDaj8io5w2bkMZzHMoyJ7kAh JqHUmflnqwTmOTI/h4VcGUH3bslfJv5wAi+cn2ezi0jr+O8Wt4kd2y+Apyf6AYyC8r0b sDQ1LeS6sKobQ0n2zDNYPWwQs42XJuH+XZFtrDhUMQFO4Kpr32aOlXJuBiqyT2UhdQe5 cw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:06 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:57 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.7 via Frontend Transport; Wed, 18 Jan 2023 10:04:57 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 934D811CC; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 5/8] ASoC: cs42l42: Export some functions for Soundwire Date: Wed, 18 Jan 2023 16:04:49 +0000 Message-ID: <20230118160452.2385494-6-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: e0TwxmiCoLTa6zUv4AqYAIA2xNmwJPWj X-Proofpoint-ORIG-GUID: e0TwxmiCoLTa6zUv4AqYAIA2xNmwJPWj X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald Export functions that will be needed by a Soundwire module. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding --- sound/soc/codecs/cs42l42.c | 14 +++++++++----- sound/soc/codecs/cs42l42.h | 5 +++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index d81c6eb1c1e59..cefefd7061689 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -653,8 +653,8 @@ static const struct cs42l42_pll_params pll_ratio_table[= ] =3D { { 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1} }; =20 -static int cs42l42_pll_config(struct snd_soc_component *component, unsigne= d int clk, - unsigned int sample_rate) +int cs42l42_pll_config(struct snd_soc_component *component, unsigned int c= lk, + unsigned int sample_rate) { struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); int i; @@ -740,8 +740,9 @@ static int cs42l42_pll_config(struct snd_soc_component = *component, unsigned int =20 return -EINVAL; } +EXPORT_SYMBOL_NS_GPL(cs42l42_pll_config, SND_SOC_CS42L42_CORE); =20 -static void cs42l42_src_config(struct snd_soc_component *component, unsign= ed int sample_rate) +void cs42l42_src_config(struct snd_soc_component *component, unsigned int = sample_rate) { struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); unsigned int fs; @@ -773,6 +774,7 @@ static void cs42l42_src_config(struct snd_soc_component= *component, unsigned int CS42L42_CLK_OASRC_SEL_MASK, fs << CS42L42_CLK_OASRC_SEL_SHIFT); } +EXPORT_SYMBOL_NS_GPL(cs42l42_src_config, SND_SOC_CS42L42_CORE); =20 static int cs42l42_asp_config(struct snd_soc_component *component, unsigned int sclk, unsigned int sample_rate) @@ -1013,7 +1015,7 @@ static int cs42l42_set_bclk_ratio(struct snd_soc_dai = *dai, return 0; } =20 -static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stre= am) +int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component =3D dai->component; struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(compone= nt); @@ -1106,6 +1108,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *da= i, int mute, int stream) =20 return 0; } +EXPORT_SYMBOL_NS_GPL(cs42l42_mute_stream, SND_SOC_CS42L42_CORE); =20 #define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ @@ -1648,7 +1651,7 @@ static const struct cs42l42_irq_params irq_params_tab= le[] =3D { CS42L42_TSRS_PLUG_VAL_MASK} }; =20 -static irqreturn_t cs42l42_irq_thread(int irq, void *data) +irqreturn_t cs42l42_irq_thread(int irq, void *data) { struct cs42l42_private *cs42l42 =3D (struct cs42l42_private *)data; unsigned int stickies[12]; @@ -1765,6 +1768,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *= data) =20 return IRQ_HANDLED; } +EXPORT_SYMBOL_NS_GPL(cs42l42_irq_thread, SND_SOC_CS42L42_CORE); =20 static void cs42l42_set_interrupt_masks(struct cs42l42_private *cs42l42) { diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 17aab06adc8e6..ef8219f489100 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -61,6 +61,11 @@ extern struct snd_soc_dai_driver cs42l42_dai; bool cs42l42_readable_register(struct device *dev, unsigned int reg); bool cs42l42_volatile_register(struct device *dev, unsigned int reg); =20 +int cs42l42_pll_config(struct snd_soc_component *component, + unsigned int clk, unsigned int sample_rate); +void cs42l42_src_config(struct snd_soc_component *component, unsigned int = sample_rate); +int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream); +irqreturn_t cs42l42_irq_thread(int irq, void *data); int cs42l42_suspend(struct device *dev); int cs42l42_resume(struct device *dev); void cs42l42_resume_restore(struct device *dev); --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4681AC678D6 for ; Wed, 18 Jan 2023 16:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231480AbjARQKc (ORCPT ); Wed, 18 Jan 2023 11:10:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229606AbjARQJG (ORCPT ); Wed, 18 Jan 2023 11:09:06 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87285470AB for ; Wed, 18 Jan 2023 08:05:17 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgrA022836; Wed, 18 Jan 2023 10:05:07 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=sH10F5Uq+zu6kLmO2UsQQuL8jGFNwsKkMKXdoWip9Pc=; b=faEiYtLuAEUHmdktLcxBAcLSY3V6sywH3BbsuaPezRIq1bTNTi5753zS7+VmW8d1ewVQ nwJLXec0kujadWBGKFfGWxE5cu8wEoLajltnp+kfyEUtbXxPWdvvcgnB22LER7PfzDuR BhxcWqPtPf8FitoiKs3aGfsFlQkcFqwzrUeZrzpEcKteNid0ASTPDPFHWluj31CACPD4 hs7c9dk7a7mEpw+cwoA4ELC75nK641hLTYcjFpHjFCT1SIZUMgX9s0m9ViobqD/YDEw9 P0DAbOxkadlWSmDoHlDBaKQEPvV8pv0dWOX2ghSyhxJaoPfTuER1TUWjPYCccOyzCaN1 fg== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:07 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:58 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.7 via Frontend Transport; Wed, 18 Jan 2023 10:04:58 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id BF15AB12; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 6/8] ASoC: cs42l42: Add Soundwire support Date: Wed, 18 Jan 2023 16:04:50 +0000 Message-ID: <20230118160452.2385494-7-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: UdZikLge2Cw41l73afDnBsPCDg5zh5-n X-Proofpoint-ORIG-GUID: UdZikLge2Cw41l73afDnBsPCDg5zh5-n X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald This adds support for using CS42L42 as a Soundwire device. Soundwire-specifics are kept separate from the I2S implementation as much as possible, aiming to limit the risk of breaking the I2C+I2S support. There are some important differences in the silicon behaviour between I2S and Soundwire mode that are reflected in the implementation: - ASP (I2S) most not be used in Soundwire mode because the two interfaces share pins. - The Soundwire capture (record) port only supports 1 channel. It does not have left-to-right duplication like the ASP. - DP2 can only be prepared if the HP has powered-up. DP1 can only be prepared if the ADC has powered-up. (This ordering restriction does not exist for ASPs.) The Soundwire core port-prepare step is triggered by the DAI-link prepare(). This happens before the codec DAI prepare() or the DAPM sequence so these cannot be used to enable HP/ADC. Instead the HP/ADC enable/disable are done during the port_prep callback. - The SRCs are an integral part of the audio chain but in silicon their power control is linked to the ASP. There is no equivalent power link to Soundwire DPs so the driver must take "manual" control of SRC power. - The Soundwire control registers occupy the lower part of the Soundwire address space so cs42l42 registers are offset by 0x8000 (non-paged) in Soundwire mode. - Register addresses are 8-bit paged in I2C mode but 16-bit unpaged in Soundwire. - Special procedures are needed on register read/writes to (a) ensure that the previous internal bus transaction has completed, and (b) handle delayed read results, when the read value could not be returned within the Soundwire read command. There are also some differences in driver implementation between I2S and Soundwire operation: - CS42L42 does not runtime_suspend, but runtime_suspend/resume are required in Soundwire mode as the most convenient way to power-up the bus manager and to handle the unattach_request condition. - Intel Soundwire host controllers have a low-power clock-stop mode that requires resetting all peripherals when resuming. This means that the interrupt registers will be reset in between the interrupt being generated and the interrupt being handled, and since the interrupt status is debounced, these values may not be accurrate immediately, and may cause spurious unplug events before settling. - As in I2S mode, the PLL is only used while audio is active because of clocking quirks in the silicon. For Soundwire the cs42l42_pll_config() is deferred until the DAI prepare(), to allow the cs42l42_bus_config() callback to set the SCLK. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding --- sound/soc/codecs/Kconfig | 8 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs42l42-sdw.c | 595 +++++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l42.c | 21 ++ sound/soc/codecs/cs42l42.h | 3 + 5 files changed, 629 insertions(+) create mode 100644 sound/soc/codecs/cs42l42-sdw.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6b4ee14640abc..1e5558f0c7b2a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -68,6 +68,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS35L45_I2C imply SND_SOC_CS35L45_SPI imply SND_SOC_CS42L42 + imply SND_SOC_CS42L42_SDW imply SND_SOC_CS42L51_I2C imply SND_SOC_CS42L52 imply SND_SOC_CS42L56 @@ -703,6 +704,13 @@ config SND_SOC_CS42L42 select REGMAP_I2C select SND_SOC_CS42L42_CORE =20 +config SND_SOC_CS42L42_SDW + tristate "Cirrus Logic CS42L42 CODEC on Soundwire" + depends on SOUNDWIRE + select SND_SOC_CS42L42_CORE + help + Enable support for Cirrus Logic CS42L42 codec with Soundwire control + config SND_SOC_CS42L51 tristate =20 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 71d3ce5867e4f..31c8921028cce 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -66,6 +66,7 @@ snd-soc-cs35l45-spi-objs :=3D cs35l45-spi.o snd-soc-cs35l45-i2c-objs :=3D cs35l45-i2c.o snd-soc-cs42l42-objs :=3D cs42l42.o snd-soc-cs42l42-i2c-objs :=3D cs42l42-i2c.o +snd-soc-cs42l42-sdw-objs :=3D cs42l42-sdw.o snd-soc-cs42l51-objs :=3D cs42l51.o snd-soc-cs42l51-i2c-objs :=3D cs42l51-i2c.o snd-soc-cs42l52-objs :=3D cs42l52.o @@ -427,6 +428,7 @@ obj-$(CONFIG_SND_SOC_CS35L45_SPI) +=3D snd-soc-cs35l45-= spi.o obj-$(CONFIG_SND_SOC_CS35L45_I2C) +=3D snd-soc-cs35l45-i2c.o obj-$(CONFIG_SND_SOC_CS42L42_CORE) +=3D snd-soc-cs42l42.o obj-$(CONFIG_SND_SOC_CS42L42) +=3D snd-soc-cs42l42-i2c.o +obj-$(CONFIG_SND_SOC_CS42L42_SDW) +=3D snd-soc-cs42l42-sdw.o obj-$(CONFIG_SND_SOC_CS42L51) +=3D snd-soc-cs42l51.o obj-$(CONFIG_SND_SOC_CS42L51_I2C) +=3D snd-soc-cs42l51-i2c.o obj-$(CONFIG_SND_SOC_CS42L52) +=3D snd-soc-cs42l52.o diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c new file mode 100644 index 0000000000000..67800b275e422 --- /dev/null +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0-only +// cs42l42-sdw.c -- CS42L42 ALSA SoC audio driver Soundwire binding +// +// Copyright (C) 2022 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs42l42.h" + +#define CS42L42_SDW_CAPTURE_PORT 1 +#define CS42L42_SDW_PLAYBACK_PORT 2 + +/* Register addresses are offset when sent over Soundwire */ +#define CS42L42_SDW_ADDR_OFFSET 0x8000 + +#define CS42L42_SDW_MEM_ACCESS_STATUS 0xd0 +#define CS42L42_SDW_MEM_READ_DATA 0xd8 + +#define CS42L42_SDW_LAST_LATE BIT(3) +#define CS42L42_SDW_CMD_IN_PROGRESS BIT(2) +#define CS42L42_SDW_RDATA_RDY BIT(0) + +#define CS42L42_DELAYED_READ_POLL_US 1 +#define CS42L42_DELAYED_READ_TIMEOUT_US 100 + +static const struct snd_soc_dapm_route cs42l42_sdw_audio_map[] =3D { + /* Playback Path */ + { "HP", NULL, "MIXER" }, + { "MIXER", NULL, "DACSRC" }, + { "DACSRC", NULL, "Playback" }, + + /* Capture Path */ + { "ADCSRC", NULL, "HS" }, + { "Capture", NULL, "ADCSRC" }, +}; + +static int cs42l42_sdw_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(dai->co= mponent); + + if (!cs42l42->init_done) + return -ENODEV; + + return 0; +} + +static int cs42l42_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(dai->co= mponent); + struct sdw_stream_runtime *sdw_stream =3D snd_soc_dai_get_dma_data(dai, s= ubstream); + struct sdw_stream_config stream_config =3D {0}; + struct sdw_port_config port_config =3D {0}; + int ret; + + if (!sdw_stream) + return -EINVAL; + + /* Needed for PLL configuration when we are notified of new bus config */ + cs42l42->sample_rate =3D params_rate(params); + + snd_sdw_params_to_config(substream, params, &stream_config, &port_config); + + if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + port_config.num =3D CS42L42_SDW_PLAYBACK_PORT; + else + port_config.num =3D CS42L42_SDW_CAPTURE_PORT; + + ret =3D sdw_stream_add_slave(cs42l42->sdw_peripheral, &stream_config, &po= rt_config, 1, + sdw_stream); + if (ret) { + dev_err(dai->dev, "Failed to add sdw stream: %d\n", ret); + return ret; + } + + cs42l42_src_config(dai->component, params_rate(params)); + + return 0; +} + +static int cs42l42_sdw_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(dai->co= mponent); + + dev_dbg(dai->dev, "dai_prepare: sclk=3D%u rate=3D%u\n", cs42l42->sclk, cs= 42l42->sample_rate); + + if (!cs42l42->sclk || !cs42l42->sample_rate) + return -EINVAL; + + return cs42l42_pll_config(dai->component, cs42l42->sclk, cs42l42->sample_= rate); +} + +static int cs42l42_sdw_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct cs42l42_private *cs42l42 =3D snd_soc_component_get_drvdata(dai->co= mponent); + struct sdw_stream_runtime *sdw_stream =3D snd_soc_dai_get_dma_data(dai, s= ubstream); + + sdw_stream_remove_slave(cs42l42->sdw_peripheral, sdw_stream); + cs42l42->sample_rate =3D 0; + + return 0; +} + +static int cs42l42_sdw_port_prep(struct sdw_slave *slave, + struct sdw_prepare_ch *prepare_ch, + enum sdw_port_prep_ops state) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&slave->dev); + unsigned int pdn_mask; + + if (prepare_ch->num =3D=3D CS42L42_SDW_PLAYBACK_PORT) + pdn_mask =3D CS42L42_HP_PDN_MASK; + else + pdn_mask =3D CS42L42_ADC_PDN_MASK; + + if (state =3D=3D SDW_OPS_PORT_PRE_PREP) { + dev_dbg(cs42l42->dev, "Prep Port pdn_mask:%x\n", pdn_mask); + regmap_clear_bits(cs42l42->regmap, CS42L42_PWR_CTL1, pdn_mask); + usleep_range(CS42L42_HP_ADC_EN_TIME_US, CS42L42_HP_ADC_EN_TIME_US + 1000= ); + } else if (state =3D=3D SDW_OPS_PORT_POST_DEPREP) { + dev_dbg(cs42l42->dev, "Deprep Port pdn_mask:%x\n", pdn_mask); + regmap_set_bits(cs42l42->regmap, CS42L42_PWR_CTL1, pdn_mask); + } + + return 0; +} + +static int cs42l42_sdw_dai_set_sdw_stream(struct snd_soc_dai *dai, void *s= dw_stream, + int direction) +{ + if (!sdw_stream) + return 0; + + if (direction =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data =3D sdw_stream; + else + dai->capture_dma_data =3D sdw_stream; + + return 0; +} + +static void cs42l42_sdw_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static const struct snd_soc_dai_ops cs42l42_sdw_dai_ops =3D { + .startup =3D cs42l42_sdw_dai_startup, + .shutdown =3D cs42l42_sdw_dai_shutdown, + .hw_params =3D cs42l42_sdw_dai_hw_params, + .prepare =3D cs42l42_sdw_dai_prepare, + .hw_free =3D cs42l42_sdw_dai_hw_free, + .mute_stream =3D cs42l42_mute_stream, + .set_stream =3D cs42l42_sdw_dai_set_sdw_stream, +}; + +static struct snd_soc_dai_driver cs42l42_sdw_dai =3D { + .name =3D "cs42l42-sdw", + .playback =3D { + .stream_name =3D "Playback", + .channels_min =3D 1, + .channels_max =3D 2, + .rates =3D SNDRV_PCM_RATE_8000_96000, + .formats =3D SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture =3D { + .stream_name =3D "Capture", + .channels_min =3D 1, + .channels_max =3D 1, + .rates =3D SNDRV_PCM_RATE_8000_96000, + .formats =3D SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .symmetric_rate =3D 1, + .ops =3D &cs42l42_sdw_dai_ops, +}; + +static int cs42l42_sdw_poll_status(struct sdw_slave *peripheral, u8 mask, = u8 match) +{ + int ret, sdwret; + + ret =3D read_poll_timeout(sdw_read_no_pm, sdwret, + (sdwret < 0) || ((sdwret & mask) =3D=3D match), + CS42L42_DELAYED_READ_POLL_US, CS42L42_DELAYED_READ_TIMEOUT_US, + false, peripheral, CS42L42_SDW_MEM_ACCESS_STATUS); + if (ret =3D=3D 0) + ret =3D sdwret; + + if (ret < 0) + dev_err(&peripheral->dev, "MEM_ACCESS_STATUS & %#x for %#x fail: %d\n", + mask, match, ret); + + return ret; +} + +static int cs42l42_sdw_read(void *context, unsigned int reg, unsigned int = *val) +{ + struct sdw_slave *peripheral =3D context; + u8 data; + int ret; + + reg +=3D CS42L42_SDW_ADDR_OFFSET; + + ret =3D cs42l42_sdw_poll_status(peripheral, CS42L42_SDW_CMD_IN_PROGRESS, = 0); + if (ret < 0) + return ret; + + ret =3D sdw_read_no_pm(peripheral, reg); + if (ret < 0) { + dev_err(&peripheral->dev, "Failed to issue read @0x%x: %d\n", reg, ret); + return ret; + } + + data =3D (u8)ret; /* possible non-delayed read value */ + ret =3D sdw_read_no_pm(peripheral, CS42L42_SDW_MEM_ACCESS_STATUS); + if (ret < 0) { + dev_err(&peripheral->dev, "Failed to read MEM_ACCESS_STATUS: %d\n", ret); + return ret; + } + + /* If read was not delayed we already have the result */ + if ((ret & CS42L42_SDW_LAST_LATE) =3D=3D 0) { + *val =3D data; + return 0; + } + + /* Poll for delayed read completion */ + if ((ret & CS42L42_SDW_RDATA_RDY) =3D=3D 0) { + ret =3D cs42l42_sdw_poll_status(peripheral, + CS42L42_SDW_RDATA_RDY, CS42L42_SDW_RDATA_RDY); + if (ret < 0) + return ret; + } + + ret =3D sdw_read_no_pm(peripheral, CS42L42_SDW_MEM_READ_DATA); + if (ret < 0) { + dev_err(&peripheral->dev, "Failed to read READ_DATA: %d\n", ret); + return ret; + } + + *val =3D (u8)ret; + + return 0; +} + +static int cs42l42_sdw_write(void *context, unsigned int reg, unsigned int= val) +{ + struct sdw_slave *peripheral =3D context; + int ret; + + ret =3D cs42l42_sdw_poll_status(peripheral, CS42L42_SDW_CMD_IN_PROGRESS, = 0); + if (ret < 0) + return ret; + + return sdw_write_no_pm(peripheral, reg + CS42L42_SDW_ADDR_OFFSET, (u8)val= ); +} + +static void cs42l42_sdw_init(struct sdw_slave *peripheral) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + int ret =3D 0; + + regcache_cache_only(cs42l42->regmap, false); + + ret =3D cs42l42_init(cs42l42); + if (ret < 0) { + regcache_cache_only(cs42l42->regmap, true); + return; + } + + /* Write out any cached changes that happened between probe and attach */ + ret =3D regcache_sync(cs42l42->regmap); + if (ret < 0) + dev_warn(cs42l42->dev, "Failed to sync cache: %d\n", ret); + + /* Disable internal logic that makes clock-stop conditional */ + regmap_clear_bits(cs42l42->regmap, CS42L42_PWR_CTL3, CS42L42_SW_CLK_STP_S= TAT_SEL_MASK); + + /* + * pm_runtime is needed to control bus manager suspend, and to + * recover from an unattach_request when the manager suspends. + * Autosuspend delay must be long enough to enumerate. + */ + pm_runtime_set_autosuspend_delay(cs42l42->dev, 3000); + pm_runtime_use_autosuspend(cs42l42->dev); + pm_runtime_set_active(cs42l42->dev); + pm_runtime_enable(cs42l42->dev); + pm_runtime_mark_last_busy(cs42l42->dev); + pm_runtime_idle(cs42l42->dev); +} + +static int cs42l42_sdw_read_prop(struct sdw_slave *peripheral) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + struct sdw_slave_prop *prop =3D &peripheral->prop; + struct sdw_dpn_prop *ports; + + ports =3D devm_kcalloc(cs42l42->dev, 2, sizeof(*ports), GFP_KERNEL); + if (!ports) + return -ENOMEM; + + prop->source_ports =3D BIT(CS42L42_SDW_CAPTURE_PORT); + prop->sink_ports =3D BIT(CS42L42_SDW_PLAYBACK_PORT); + prop->quirks =3D SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->scp_int1_mask =3D SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + + /* DP1 - capture */ + ports[0].num =3D CS42L42_SDW_CAPTURE_PORT, + ports[0].type =3D SDW_DPN_FULL, + ports[0].ch_prep_timeout =3D 10, + prop->src_dpn_prop =3D &ports[0]; + + /* DP2 - playback */ + ports[1].num =3D CS42L42_SDW_PLAYBACK_PORT, + ports[1].type =3D SDW_DPN_FULL, + ports[1].ch_prep_timeout =3D 10, + prop->sink_dpn_prop =3D &ports[1]; + + return 0; +} + +static int cs42l42_sdw_update_status(struct sdw_slave *peripheral, + enum sdw_slave_status status) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + + switch (status) { + case SDW_SLAVE_ATTACHED: + dev_dbg(cs42l42->dev, "ATTACHED\n"); + if (!cs42l42->init_done) + cs42l42_sdw_init(peripheral); + break; + case SDW_SLAVE_UNATTACHED: + dev_dbg(cs42l42->dev, "UNATTACHED\n"); + break; + default: + break; + } + + return 0; +} + +static int cs42l42_sdw_bus_config(struct sdw_slave *peripheral, + struct sdw_bus_params *params) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + unsigned int new_sclk =3D params->curr_dr_freq / 2; + + /* The cs42l42 cannot support a glitchless SWIRE_CLK change. */ + if ((new_sclk !=3D cs42l42->sclk) && cs42l42->stream_use) { + dev_warn(cs42l42->dev, "Rejected SCLK change while audio active\n"); + return -EBUSY; + } + + cs42l42->sclk =3D new_sclk; + + dev_dbg(cs42l42->dev, "bus_config: sclk=3D%u c=3D%u r=3D%u\n", + cs42l42->sclk, params->col, params->row); + + return 0; +} + +static int __maybe_unused cs42l42_sdw_clk_stop(struct sdw_slave *periphera= l, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + + dev_dbg(cs42l42->dev, "clk_stop mode:%d type:%d\n", mode, type); + + return 0; +} + +static const struct sdw_slave_ops cs42l42_sdw_ops =3D { + .read_prop =3D cs42l42_sdw_read_prop, + .update_status =3D cs42l42_sdw_update_status, + .bus_config =3D cs42l42_sdw_bus_config, + .port_prep =3D cs42l42_sdw_port_prep, +#ifdef DEBUG + .clk_stop =3D cs42l42_sdw_clk_stop, +#endif +}; + +static int __maybe_unused cs42l42_sdw_runtime_suspend(struct device *dev) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(dev); + + dev_dbg(dev, "Runtime suspend\n"); + + /* The host controller could suspend, which would mean no register access= */ + regcache_cache_only(cs42l42->regmap, true); + + return 0; +} + +static const struct reg_sequence __maybe_unused cs42l42_soft_reboot_seq[] = =3D { + REG_SEQ0(CS42L42_SOFT_RESET_REBOOT, 0x1e), +}; + +static int __maybe_unused cs42l42_sdw_handle_unattach(struct cs42l42_priva= te *cs42l42) +{ + struct sdw_slave *peripheral =3D cs42l42->sdw_peripheral; + + if (!peripheral->unattach_request) + return 0; + + /* Cannot access registers until master re-attaches. */ + dev_dbg(&peripheral->dev, "Wait for initialization_complete\n"); + if (!wait_for_completion_timeout(&peripheral->initialization_complete, + msecs_to_jiffies(5000))) { + dev_err(&peripheral->dev, "initialization_complete timed out\n"); + return -ETIMEDOUT; + } + + peripheral->unattach_request =3D 0; + + /* + * After a bus reset there must be a reconfiguration reset to + * reinitialize the internal state of CS42L42. + */ + regmap_multi_reg_write_bypassed(cs42l42->regmap, + cs42l42_soft_reboot_seq, + ARRAY_SIZE(cs42l42_soft_reboot_seq)); + usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); + regcache_mark_dirty(cs42l42->regmap); + + return 0; +} + +static int __maybe_unused cs42l42_sdw_runtime_resume(struct device *dev) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "Runtime resume\n"); + + ret =3D cs42l42_sdw_handle_unattach(cs42l42); + if (ret < 0) + return ret; + + regcache_cache_only(cs42l42->regmap, false); + + /* Sync LATCH_TO_VP first so the VP domain registers sync correctly */ + regcache_sync_region(cs42l42->regmap, CS42L42_MIC_DET_CTL1, CS42L42_MIC_D= ET_CTL1); + regcache_sync(cs42l42->regmap); + + return 0; +} + +static int __maybe_unused cs42l42_sdw_resume(struct device *dev) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "System resume\n"); + + /* Power-up so it can re-enumerate */ + ret =3D cs42l42_resume(dev); + if (ret) + return ret; + + /* Wait for re-attach */ + ret =3D cs42l42_sdw_handle_unattach(cs42l42); + if (ret < 0) + return ret; + + cs42l42_resume_restore(dev); + + return 0; +} + +static int cs42l42_sdw_probe(struct sdw_slave *peripheral, const struct sd= w_device_id *id) +{ + struct snd_soc_component_driver *component_drv; + struct device *dev =3D &peripheral->dev; + struct cs42l42_private *cs42l42; + struct regmap_config *regmap_conf; + struct regmap *regmap; + int irq, ret; + + cs42l42 =3D devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL); + if (!cs42l42) + return -ENOMEM; + + if (has_acpi_companion(dev)) + irq =3D acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0); + else + irq =3D of_irq_get(dev->of_node, 0); + + if (irq =3D=3D -ENOENT) + irq =3D 0; + else if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get IRQ\n"); + + regmap_conf =3D devm_kmemdup(dev, &cs42l42_regmap, sizeof(cs42l42_regmap)= , GFP_KERNEL); + if (!regmap_conf) + return -ENOMEM; + regmap_conf->reg_bits =3D 16; + regmap_conf->num_ranges =3D 0; + regmap_conf->reg_read =3D cs42l42_sdw_read; + regmap_conf->reg_write =3D cs42l42_sdw_write; + + regmap =3D devm_regmap_init(dev, NULL, peripheral, regmap_conf); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to allocate register = map\n"); + + /* Start in cache-only until device is enumerated */ + regcache_cache_only(regmap, true); + + component_drv =3D devm_kmemdup(dev, + &cs42l42_soc_component, + sizeof(cs42l42_soc_component), + GFP_KERNEL); + if (!component_drv) + return -ENOMEM; + + component_drv->dapm_routes =3D cs42l42_sdw_audio_map; + component_drv->num_dapm_routes =3D ARRAY_SIZE(cs42l42_sdw_audio_map); + + cs42l42->dev =3D dev; + cs42l42->regmap =3D regmap; + cs42l42->sdw_peripheral =3D peripheral; + cs42l42->irq =3D irq; + cs42l42->devid =3D CS42L42_CHIP_ID; + + ret =3D cs42l42_common_probe(cs42l42, component_drv, &cs42l42_sdw_dai); + if (ret < 0) + return ret; + + return 0; +} + +static int cs42l42_sdw_remove(struct sdw_slave *peripheral) +{ + struct cs42l42_private *cs42l42 =3D dev_get_drvdata(&peripheral->dev); + + /* Resume so that cs42l42_remove() can access registers */ + pm_runtime_get_sync(cs42l42->dev); + cs42l42_common_remove(cs42l42); + pm_runtime_put(cs42l42->dev); + pm_runtime_disable(cs42l42->dev); + + return 0; +} + +static const struct dev_pm_ops cs42l42_sdw_pm =3D { + SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_sdw_resume) + SET_RUNTIME_PM_OPS(cs42l42_sdw_runtime_suspend, cs42l42_sdw_runtime_resum= e, NULL) +}; + +static const struct sdw_device_id cs42l42_sdw_id[] =3D { + SDW_SLAVE_ENTRY(0x01FA, 0x4242, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, cs42l42_sdw_id); + +static struct sdw_driver cs42l42_sdw_driver =3D { + .driver =3D { + .name =3D "cs42l42-sdw", + .pm =3D &cs42l42_sdw_pm, + }, + .probe =3D cs42l42_sdw_probe, + .remove =3D cs42l42_sdw_remove, + .ops =3D &cs42l42_sdw_ops, + .id_table =3D cs42l42_sdw_id, +}; + +module_sdw_driver(cs42l42_sdw_driver); + +MODULE_DESCRIPTION("ASoC CS42L42 Soundwire driver"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE); diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index cefefd7061689..a92499876ce2a 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -525,6 +526,10 @@ static const struct snd_soc_dapm_widget cs42l42_dapm_w= idgets[] =3D { =20 /* Playback/Capture Requirements */ SND_SOC_DAPM_SUPPLY("SCLK", CS42L42_ASP_CLK_CFG, CS42L42_ASP_SCLK_EN_SHIF= T, 0, NULL, 0), + + /* Soundwire SRC power control */ + SND_SOC_DAPM_PGA("DACSRC", CS42L42_PWR_CTL2, CS42L42_DAC_SRC_PDNB_SHIFT, = 0, NULL, 0), + SND_SOC_DAPM_PGA("ADCSRC", CS42L42_PWR_CTL2, CS42L42_ADC_SRC_PDNB_SHIFT, = 0, NULL, 0), }; =20 static const struct snd_soc_dapm_route cs42l42_audio_map[] =3D { @@ -1660,9 +1665,11 @@ irqreturn_t cs42l42_irq_thread(int irq, void *data) unsigned int current_button_status; unsigned int i; =20 + pm_runtime_get_sync(cs42l42->dev); mutex_lock(&cs42l42->irq_lock); if (cs42l42->suspended || !cs42l42->init_done) { mutex_unlock(&cs42l42->irq_lock); + pm_runtime_put_autosuspend(cs42l42->dev); return IRQ_NONE; } =20 @@ -1765,6 +1772,8 @@ irqreturn_t cs42l42_irq_thread(int irq, void *data) } =20 mutex_unlock(&cs42l42->irq_lock); + pm_runtime_mark_last_busy(cs42l42->dev); + pm_runtime_put_autosuspend(cs42l42->dev); =20 return IRQ_HANDLED; } @@ -2388,6 +2397,18 @@ int cs42l42_init(struct cs42l42_private *cs42l42) if (ret !=3D 0) goto err_shutdown; =20 + /* + * SRC power is linked to ASP power so doesn't work in Soundwire mode. + * Override it and use DAPM to control SRC power for Soundwire. + */ + if (cs42l42->sdw_peripheral) { + regmap_update_bits(cs42l42->regmap, CS42L42_PWR_CTL2, + CS42L42_SRC_PDN_OVERRIDE_MASK | + CS42L42_DAC_SRC_PDNB_MASK | + CS42L42_ADC_SRC_PDNB_MASK, + CS42L42_SRC_PDN_OVERRIDE_MASK); + } + /* Setup headset detection */ cs42l42_setup_hs_type_detect(cs42l42); =20 diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index ef8219f489100..4bd7b85a57471 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,11 +31,13 @@ struct cs42l42_private { struct gpio_desc *reset_gpio; struct completion pdn_done; struct snd_soc_jack *jack; + struct sdw_slave *sdw_peripheral; struct mutex irq_lock; int devid; int irq; int pll_config; u32 sclk; + u32 sample_rate; u32 bclk_ratio; u8 plug_state; u8 hs_type; --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE3E4C32793 for ; Wed, 18 Jan 2023 16:09:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230256AbjARQJh (ORCPT ); Wed, 18 Jan 2023 11:09:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229718AbjARQJF (ORCPT ); Wed, 18 Jan 2023 11:09:05 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 31D3446159 for ; Wed, 18 Jan 2023 08:05:17 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEDgrB022836; Wed, 18 Jan 2023 10:05:08 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=frUZfxKkTDkW87u5OQbfX6rw2QFXA5a5bNSyUepkgBc=; b=E3JIXvjHd/ksH23puwvZaV/38rQ5qDiH5szpk6owT2rX7sNDj9Ok5Ye+6U2MtHL3Vw1T FcAzKWiUca/5rPmnUJ76aFd4kIKioPDnav5Xx0i3Fxfj2CJLrmJhd8pAV5P8ymJ0TpPy OOucnoUgWROiEZ5UZVg3Dc3R0idqh5o5+qfAWDMvEY7eI6WJPinxMYLmDY0428xoAX1n hN1ie6extehDTziAHyqQ9ugPq+ReC7VbOxbSToeg9NvSbuuCJC6ce5ohvRu2EPWSpzG4 amXYoqKZrIlWKhnUJKxA3USneIhvxASvivpkA0365vG7/CfS3PqlWXkDqeC22HICw7m7 og== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk9-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:08 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:58 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.7 via Frontend Transport; Wed, 18 Jan 2023 10:04:58 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id ED30B11CB; Wed, 18 Jan 2023 16:04:57 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Richard Fitzgerald , Stefan Binding Subject: [PATCH v2 7/8] ASoC: cs42l42: Don't set idle_bias_on Date: Wed, 18 Jan 2023 16:04:51 +0000 Message-ID: <20230118160452.2385494-8-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: lo4yHFbhzh4p8Z6_5t_7Dhw_IJrSF4LQ X-Proofpoint-ORIG-GUID: lo4yHFbhzh4p8Z6_5t_7Dhw_IJrSF4LQ X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Richard Fitzgerald idle_bias_on was set because cs42l42 has a "VMID" type pseudo-midrail supply (named FILT+), and these typically take a long time to charge. But the driver never enabled pm_runtime so it would never have powered- down the cs42l42 anyway. In fact, FILT+ can charge to operating voltage within 12.5 milliseconds of enabling HP or ADC. This time is already covered by the startup delay of the HP/ADC. The datasheet warning about FILT+ taking up to 1 second to charge only applies in the special cases that either the PLL is started or DETECT_MODE set to non-zero while both HP and ADC are off. The driver never does either of these. Removing idle_bias_on allows the Soundwire host controller to suspend if there isn't a snd_soc_jack handler registered. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding --- sound/soc/codecs/cs42l42.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index a92499876ce2a..aa2223bfb885a 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -597,7 +597,6 @@ const struct snd_soc_component_driver cs42l42_soc_compo= nent =3D { .num_dapm_routes =3D ARRAY_SIZE(cs42l42_audio_map), .controls =3D cs42l42_snd_controls, .num_controls =3D ARRAY_SIZE(cs42l42_snd_controls), - .idle_bias_on =3D 1, .endianness =3D 1, }; EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE); --=20 2.34.1 From nobody Sun Sep 14 20:21:19 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4AA6C46467 for ; Wed, 18 Jan 2023 16:11:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231225AbjARQKH (ORCPT ); Wed, 18 Jan 2023 11:10:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230423AbjARQJG (ORCPT ); Wed, 18 Jan 2023 11:09:06 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D5EB4743D for ; Wed, 18 Jan 2023 08:05:19 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30IEEjlB023722; Wed, 18 Jan 2023 10:05:04 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=4DC3FmrYnv3q+s9o9tP2DW9U1wOvwrAGTeF6A0jvBHQ=; b=SoRyZtEWS0ZMCaGg/MbazhydcTToCQHnCi7BeNte9Dd5nEPp9FoRk1I1GjIm0ph4AEvf 7mE7JIM2JYkMkwRvBTeEQttvDyUeaJCZACz39yzJHInM9sRlF7CuUZQWvSGhJ9zPGNXt iAy5QLIJnSrFC7Gnl8X9HqkhmJ8gNvG/orTs0ymCic3D1CJno3nWn4m+c/K7cdXRA+xm wy8cfNVxZkjLapoHGEr9O+Z4QDSSH9bjY7c5StuipDFnzVClxucUjAlHrR42oWlAb5Lf pF99rI61ds6Dw3Ko4hj8czopOjiUHAbydhs4ZjlxrZNkTGHx+e73EYZaJaO1uTvQR+ph Zg== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3n3spx6vk8-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2023 10:05:04 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Wed, 18 Jan 2023 10:04:58 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.21 via Frontend Transport; Wed, 18 Jan 2023 10:04:58 -0600 Received: from sbinding-cirrus-dsktp2.ad.cirrus.com (unknown [198.90.202.160]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 1A430B12; Wed, 18 Jan 2023 16:04:58 +0000 (UTC) From: Stefan Binding To: Mark Brown , Pierre-Louis Bossart CC: , , , Stefan Binding Subject: [PATCH v2 8/8] ASoC: cs42l42: Wait for debounce interval after resume Date: Wed, 18 Jan 2023 16:04:52 +0000 Message-ID: <20230118160452.2385494-9-sbinding@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> References: <20230118160452.2385494-1-sbinding@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: WuLPwJpdk5cA3HpxRI6bjl3uXaEa2-Gz X-Proofpoint-ORIG-GUID: WuLPwJpdk5cA3HpxRI6bjl3uXaEa2-Gz X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Since clock stop causes bus reset on Intel controllers, we need to wait for the debounce interval on resume, to ensure all the interrupt status registers are set correctly. Signed-off-by: Stefan Binding --- sound/soc/codecs/cs42l42-sdw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index 67800b275e422..27653ea0f947c 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -451,14 +451,22 @@ static int __maybe_unused cs42l42_sdw_handle_unattach= (struct cs42l42_private *cs =20 static int __maybe_unused cs42l42_sdw_runtime_resume(struct device *dev) { + static const unsigned int ts_dbnce_ms[] =3D { 0, 125, 250, 500, 750, 1000= , 1250, 1500}; struct cs42l42_private *cs42l42 =3D dev_get_drvdata(dev); + unsigned int dbnce; int ret; =20 dev_dbg(dev, "Runtime resume\n"); =20 ret =3D cs42l42_sdw_handle_unattach(cs42l42); - if (ret < 0) + if (ret < 0) { return ret; + } else if (ret > 0) { + dbnce =3D max(cs42l42->ts_dbnc_rise, cs42l42->ts_dbnc_fall); + + if (dbnce > 0) + msleep(ts_dbnce_ms[dbnce]); + } =20 regcache_cache_only(cs42l42->regmap, false); =20 --=20 2.34.1