From nobody Tue Feb 10 09:58:50 2026 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C80E83803FC for ; Tue, 13 Jan 2026 10:59:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768301981; cv=none; b=tqBCzUcEuh1MYaiK99zEYSdAr1+DRbYVzJWQivns6TtK62Uz5TxAu3JKy9nlUpf8ApAp/uD2Z7UuScvkhZdTFYmJ1bzWqf90V6T3M1nruflSfDMAzFk+5JIAUVc2+Te41K1fqNLbQvj0yN2Mqt195hylLa2RMCPrJvYXP/IJX5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768301981; c=relaxed/simple; bh=gdrzL2hpuvE/T85VvevHoKJTMlwTxRECaR7H6qpVTv4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l5t4vLPWA5YbN3OpPWPSztPuFrmZkJH/cxpyxk5XLysmNdspLgfNKMg6UJoqYieEw+ub+kXrWLFxcgZtfv+cBntZfgeOKr1GZxNrW0F0BTrzTRAvvEBuVSpJUVDXSuNrdCRUOotbAUfOVmoApKziqwWc4oYVrFyeD0b58OnNwGI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1vfc78-0008DK-Ak; Tue, 13 Jan 2026 11:59:06 +0100 Received: from dude02.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::28]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vfc74-000PMF-2n; Tue, 13 Jan 2026 11:59:02 +0100 Received: from localhost ([::1] helo=dude02.red.stw.pengutronix.de) by dude02.red.stw.pengutronix.de with esmtp (Exim 4.98.2) (envelope-from ) id 1vfc73-00000004mJf-3zOc; Tue, 13 Jan 2026 11:59:01 +0100 From: Sascha Hauer Date: Tue, 13 Jan 2026 11:58:48 +0100 Subject: [PATCH v4 05/10] ASoC: tlv320adcx140: power on/off the device on demand Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260113-sound-soc-codecs-tvl320adcx140-v4-5-8f7ecec525c8@pengutronix.de> References: <20260113-sound-soc-codecs-tvl320adcx140-v4-0-8f7ecec525c8@pengutronix.de> In-Reply-To: <20260113-sound-soc-codecs-tvl320adcx140-v4-0-8f7ecec525c8@pengutronix.de> To: Shenghao Ding , Kevin Lu , Baojun Xu , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Davis , Dan Murphy Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, Kevin Lu , linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, Sascha Hauer , Emil-Juhl X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1768301941; l=4932; i=s.hauer@pengutronix.de; s=20230412; h=from:subject:message-id; bh=0JjyB3wIqRORtMOOqEPcPC785mmT9Gy0HFJXKq2Y3dY=; b=mjN49dq5OgG4ouzHuGBbRNY4l3fJlUF3H8MRwT4LOjYgjzYYFXqwGTtrnYBgVMzOtzRQ+fijM OkRBQkOa3BdB69sjDIaG5+Pl3bCcRNxXCgSb+ZOPIq+y5qAiJmaySMV X-Developer-Key: i=s.hauer@pengutronix.de; a=ed25519; pk=4kuc9ocmECiBJKWxYgqyhtZOHj5AWi7+d0n/UjhkwTg= X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: s.hauer@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org From: Emil-Juhl The tlv320adcx140 can be connected to controllable AVDD/IOVDD regulators which when disabled will reset the registers to their default. In preparation for that switch to register writes to cache only when powered off and sync the cached values to the registers when powered back on. Signed-off-by: Emil-Juhl Signed-off-by: Sascha Hauer --- sound/soc/codecs/tlv320adcx140.c | 89 ++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx= 140.c index fdf4a9add852deb5e879dba5c8a09458fc6e709d..444c0e80f0907de201ed1818b56= 12164a48b0fca 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -121,6 +121,34 @@ static const struct reg_default adcx140_reg_defaults[]= =3D { { ADCX140_DEV_STS1, 0x80 }, }; =20 +static const struct regmap_range adcx140_wr_ranges[] =3D { + regmap_reg_range(ADCX140_PAGE_SELECT, ADCX140_SLEEP_CFG), + regmap_reg_range(ADCX140_SHDN_CFG, ADCX140_SHDN_CFG), + regmap_reg_range(ADCX140_ASI_CFG0, ADCX140_ASI_CFG2), + regmap_reg_range(ADCX140_ASI_CH1, ADCX140_MST_CFG1), + regmap_reg_range(ADCX140_CLK_SRC, ADCX140_CLK_SRC), + regmap_reg_range(ADCX140_PDMCLK_CFG, ADCX140_GPO_CFG3), + regmap_reg_range(ADCX140_GPO_VAL, ADCX140_GPO_VAL), + regmap_reg_range(ADCX140_GPI_CFG0, ADCX140_GPI_CFG1), + regmap_reg_range(ADCX140_GPI_MON, ADCX140_GPI_MON), + regmap_reg_range(ADCX140_INT_CFG, ADCX140_INT_MASK0), + regmap_reg_range(ADCX140_BIAS_CFG, ADCX140_CH4_CFG4), + regmap_reg_range(ADCX140_CH5_CFG2, ADCX140_CH5_CFG4), + regmap_reg_range(ADCX140_CH6_CFG2, ADCX140_CH6_CFG4), + regmap_reg_range(ADCX140_CH7_CFG2, ADCX140_CH7_CFG4), + regmap_reg_range(ADCX140_CH8_CFG2, ADCX140_CH8_CFG4), + regmap_reg_range(ADCX140_DSP_CFG0, ADCX140_DRE_CFG0), + regmap_reg_range(ADCX140_AGC_CFG0, ADCX140_AGC_CFG0), + regmap_reg_range(ADCX140_IN_CH_EN, ADCX140_PWR_CFG), + regmap_reg_range(ADCX140_PHASE_CALIB, ADCX140_PHASE_CALIB), + regmap_reg_range(0x7e, 0x7e), +}; + +static const struct regmap_access_table adcx140_wr_table =3D { + .yes_ranges =3D adcx140_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(adcx140_wr_ranges), +}; + static const struct regmap_range_cfg adcx140_ranges[] =3D { { .range_min =3D 0, @@ -156,6 +184,7 @@ static const struct regmap_config adcx140_i2c_regmap = =3D { .num_ranges =3D ARRAY_SIZE(adcx140_ranges), .max_register =3D 12 * 128, .volatile_reg =3D adcx140_volatile, + .wr_table =3D &adcx140_wr_table, }; =20 /* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */ @@ -1073,19 +1102,73 @@ static int adcx140_codec_probe(struct snd_soc_compo= nent *component) return ret; } =20 +static int adcx140_pwr_off(struct adcx140_priv *adcx140) +{ + regcache_cache_only(adcx140->regmap, true); + regcache_mark_dirty(adcx140->regmap); + + /* Assert the reset GPIO */ + gpiod_set_value_cansleep(adcx140->gpio_reset, 0); + + /* + * Datasheet - TLV320ADC3140 Rev. B, TLV320ADC5140 Rev. A, + * TLV320ADC6140 Rev. A 8.4.1: + * wait for hw shutdown (25ms) + >=3D 1ms + */ + usleep_range(30000, 100000); + + return 0; +} + +static int adcx140_pwr_on(struct adcx140_priv *adcx140) +{ + int ret; + + /* De-assert the reset GPIO */ + gpiod_set_value_cansleep(adcx140->gpio_reset, 1); + + /* + * Datasheet - TLV320ADC3140 Rev. B, TLV320ADC5140 Rev. A, + * TLV320ADC6140 Rev. A 8.4.2: + * wait >=3D 10 ms after entering sleep mode. + */ + usleep_range(10000, 100000); + + regcache_cache_only(adcx140->regmap, false); + + /* Flush the regcache */ + ret =3D regcache_sync(adcx140->regmap); + if (ret) { + dev_err(adcx140->dev, "Failed to restore register map: %d\n", + ret); + return ret; + } + + return 0; +} + static int adcx140_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct adcx140_priv *adcx140 =3D snd_soc_component_get_drvdata(component); + enum snd_soc_bias_level prev_level + =3D snd_soc_component_get_bias_level(component); =20 switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: + if (prev_level =3D=3D SND_SOC_BIAS_STANDBY) + adcx140_pwr_ctrl(adcx140, true); + break; case SND_SOC_BIAS_STANDBY: - adcx140_pwr_ctrl(adcx140, true); + if (prev_level =3D=3D SND_SOC_BIAS_PREPARE) + adcx140_pwr_ctrl(adcx140, false); + if (prev_level =3D=3D SND_SOC_BIAS_OFF) + return adcx140_pwr_on(adcx140); break; case SND_SOC_BIAS_OFF: - adcx140_pwr_ctrl(adcx140, false); + if (prev_level =3D=3D SND_SOC_BIAS_STANDBY) + return adcx140_pwr_off(adcx140); break; } =20 @@ -1186,6 +1269,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c) return ret; } =20 + regcache_cache_only(adcx140->regmap, true); + i2c_set_clientdata(i2c, adcx140); =20 return devm_snd_soc_register_component(&i2c->dev, --=20 2.47.3