From nobody Sat Sep 13 06:14:49 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 35867C61DA4 for ; Sat, 4 Feb 2023 21:02:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232957AbjBDVCK (ORCPT ); Sat, 4 Feb 2023 16:02:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232439AbjBDVCH (ORCPT ); Sat, 4 Feb 2023 16:02:07 -0500 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE509206AF for ; Sat, 4 Feb 2023 13:02:06 -0800 (PST) Received: by mail-pj1-x1033.google.com with SMTP id d2so4574247pjd.5 for ; Sat, 04 Feb 2023 13:02:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=igorinstitute-com.20210112.gappssmtp.com; s=20210112; h=cc:to:subject:date:from:references:in-reply-to:message-id:from:to :cc:subject:date:message-id:reply-to; bh=38D6J740N3833rshUE9U2HYtUisuJRur7dCUFd2NB3Q=; b=TdZgv/XTCjn5Ew2w8CRX1nwLXdxhnkY8cW+9DDdckH0UZOlxm20bwQaaDKw0vwBqGD +47Ab11AHGGLu0/G7uQTJmGSbUhD8HktM7W+aWbH2vTz1LFi8KRQKmHA+EX7LMWGK/XH cd/6bp7xiSllIPMU43PFbxta6sx0LJ9t6gUNyDyqqSVdGujFG1GpGUHma6+rjTTf5KiS 7xYsDEu0QFZgJ+RjKUjFBlJVAa1wqHXKXxF34hEIPK8ARFGoH+08bdRTrE71lfpW89Kk cm7sE57ZFzpr2Xu/8DoYbm09Q+lVDIHaQttzTtxIbW+hSu0SQH8sJ4AWQLbr5By+JGoa W2FA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:date:from:references:in-reply-to:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=38D6J740N3833rshUE9U2HYtUisuJRur7dCUFd2NB3Q=; b=WjVfGgGgEghxlEXZR/HRrJ29eJNzhYmJjHsMuth0GMu9zmN7qnuan9EAKxVG30glTD ZCLMXqpLd27Sc6M/PM9qO+NEvoq2wltatEMHvW1fosrV3kg8GZDjMcE7CeVAGYwPqQsL e/JhyrILQqex7vzq8gXs70lrlDEvQ7O9s2JEIFKzF4CLH2wqBYZUmP+WMpBrtKIXsgOS kWmPXqKZNi5k5djFrr9vjYbPTJgoVsgmOdsxSNGXN1Ji2Gr9fkQLV7owdrOUXZSGErZj jKX//Ev2lag36IDSv6LiPGvwQYIov4Ob/08j7iYr/p0MNyKmWO9603/xFZXVbjhAZBH6 vY0w== X-Gm-Message-State: AO0yUKW9BX8ntrC/qrPraPzJMdfinWocrxov6HVN8FSrC8BFKtGDZbRs lzKCJuPtvQjAH8wvsuXbxTVEKXe9C9r/kjNq X-Google-Smtp-Source: AK7set/qojJ+xgELZjMGFAfgEw2fG9MMcOPNCpht2AALraSNHtNUcG4xMT0qEvXDwqO2bWtVloWmZg== X-Received: by 2002:a17:902:ce91:b0:194:7efa:702f with SMTP id f17-20020a170902ce9100b001947efa702fmr18052435plg.53.1675544526143; Sat, 04 Feb 2023 13:02:06 -0800 (PST) Received: from localhost ([121.99.145.49]) by smtp.gmail.com with ESMTPSA id jj20-20020a170903049400b00194ab9a4febsm3867973plb.74.2023.02.04.13.02.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 04 Feb 2023 13:02:05 -0800 (PST) Message-Id: <85d8ba405cb009a7a3249b556dc8f3bdb1754fdf.1675497326.git.daniel.beer@igorinstitute.com> In-Reply-To: References: From: Daniel Beer Date: Thu, 27 Oct 2022 21:28:31 +1300 Subject: [PATCH v3 1/2] ASoC: tas5805m: rework to avoid scheduling while atomic. To: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org, Daniel Beer , Andy Liu , Mark Brown Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" There's some setup we need to do in order to get the DSP initialized, and this can't be done until a bit-clock is ready. In an earlier version of this driver, this work was done in a DAPM callback. The DAPM callback doesn't guarantee that the bit-clock is running, so the work was moved instead to the trigger callback. Unfortunately this callback runs in atomic context, and the setup code needs to do I2C transactions. Here we use a work_struct to kick off the setup in a thread instead. Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier") Signed-off-by: Daniel Beer --- sound/soc/codecs/tas5805m.c | 128 ++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 41 deletions(-) diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index beb4ec629a03..6e2edf045446 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] =3D { #define TAS5805M_VOLUME_MIN 0 =20 struct tas5805m_priv { + struct i2c_client *i2c; struct regulator *pvdd; struct gpio_desc *gpio_pdn_n; =20 @@ -165,6 +166,9 @@ struct tas5805m_priv { int vol[2]; bool is_powered; bool is_muted; + + struct work_struct work; + struct mutex lock; }; =20 static void set_dsp_scale(struct regmap *rm, int offset, int vol) @@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offs= et, int vol) regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v)); } =20 -static void tas5805m_refresh(struct snd_soc_component *component) +static void tas5805m_refresh(struct tas5805m_priv *tas5805m) { - struct tas5805m_priv *tas5805m =3D - snd_soc_component_get_drvdata(component); struct regmap *rm =3D tas5805m->regmap; =20 - dev_dbg(component->dev, "refresh: is_muted=3D%d, vol=3D%d/%d\n", + dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=3D%d, vol=3D%d/%d\n", tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]); =20 regmap_write(rm, REG_PAGE, 0x00); @@ -226,8 +228,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcont= rol, struct tas5805m_priv *tas5805m =3D snd_soc_component_get_drvdata(component); =20 + mutex_lock(&tas5805m->lock); ucontrol->value.integer.value[0] =3D tas5805m->vol[0]; ucontrol->value.integer.value[1] =3D tas5805m->vol[1]; + mutex_unlock(&tas5805m->lock); + return 0; } =20 @@ -243,11 +248,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcon= trol, snd_soc_kcontrol_component(kcontrol); struct tas5805m_priv *tas5805m =3D snd_soc_component_get_drvdata(component); + int ret =3D 0; =20 if (!(volume_is_valid(ucontrol->value.integer.value[0]) && volume_is_valid(ucontrol->value.integer.value[1]))) return -EINVAL; =20 + mutex_lock(&tas5805m->lock); if (tas5805m->vol[0] !=3D ucontrol->value.integer.value[0] || tas5805m->vol[1] !=3D ucontrol->value.integer.value[1]) { tas5805m->vol[0] =3D ucontrol->value.integer.value[0]; @@ -256,11 +263,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcon= trol, tas5805m->vol[0], tas5805m->vol[1], tas5805m->is_powered); if (tas5805m->is_powered) - tas5805m_refresh(component); - return 1; + tas5805m_refresh(tas5805m); + ret =3D 1; } + mutex_unlock(&tas5805m->lock); =20 - return 0; + return ret; } =20 static const struct snd_kcontrol_new tas5805m_snd_controls[] =3D { @@ -294,54 +302,83 @@ static int tas5805m_trigger(struct snd_pcm_substream = *substream, int cmd, struct snd_soc_component *component =3D dai->component; struct tas5805m_priv *tas5805m =3D snd_soc_component_get_drvdata(component); - struct regmap *rm =3D tas5805m->regmap; - unsigned int chan, global1, global2; =20 switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dev_dbg(component->dev, "DSP startup\n"); - - /* We mustn't issue any I2C transactions until the I2S - * clock is stable. Furthermore, we must allow a 5ms - * delay after the first set of register writes to - * allow the DSP to boot before configuring it. - */ - usleep_range(5000, 10000); - send_cfg(rm, dsp_cfg_preboot, - ARRAY_SIZE(dsp_cfg_preboot)); - usleep_range(5000, 15000); - send_cfg(rm, tas5805m->dsp_cfg_data, - tas5805m->dsp_cfg_len); - - tas5805m->is_powered =3D true; - tas5805m_refresh(component); + dev_dbg(component->dev, "clock start\n"); + schedule_work(&tas5805m->work); break; =20 case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dev_dbg(component->dev, "DSP shutdown\n"); + break; =20 - tas5805m->is_powered =3D false; + default: + return -EINVAL; + } =20 - regmap_write(rm, REG_PAGE, 0x00); - regmap_write(rm, REG_BOOK, 0x00); + return 0; +} =20 - regmap_read(rm, REG_CHAN_FAULT, &chan); - regmap_read(rm, REG_GLOBAL_FAULT1, &global1); - regmap_read(rm, REG_GLOBAL_FAULT2, &global2); +static void do_work(struct work_struct *work) +{ + struct tas5805m_priv *tas5805m =3D + container_of(work, struct tas5805m_priv, work); + struct regmap *rm =3D tas5805m->regmap; =20 - dev_dbg(component->dev, - "fault regs: CHAN=3D%02x, GLOBAL1=3D%02x, GLOBAL2=3D%02x\n", - chan, global1, global2); + dev_dbg(&tas5805m->i2c->dev, "DSP startup\n"); =20 - regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ); - break; + mutex_lock(&tas5805m->lock); + /* We mustn't issue any I2C transactions until the I2S + * clock is stable. Furthermore, we must allow a 5ms + * delay after the first set of register writes to + * allow the DSP to boot before configuring it. + */ + usleep_range(5000, 10000); + send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot)); + usleep_range(5000, 15000); + send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len); + + tas5805m->is_powered =3D true; + tas5805m_refresh(tas5805m); + mutex_unlock(&tas5805m->lock); +} =20 - default: - return -EINVAL; +static int tas5805m_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component =3D snd_soc_dapm_to_component(w->dapm= ); + struct tas5805m_priv *tas5805m =3D + snd_soc_component_get_drvdata(component); + struct regmap *rm =3D tas5805m->regmap; + + if (event & SND_SOC_DAPM_PRE_PMD) { + unsigned int chan, global1, global2; + + dev_dbg(component->dev, "DSP shutdown\n"); + cancel_work_sync(&tas5805m->work); + + mutex_lock(&tas5805m->lock); + if (tas5805m->is_powered) { + tas5805m->is_powered =3D false; + + regmap_write(rm, REG_PAGE, 0x00); + regmap_write(rm, REG_BOOK, 0x00); + + regmap_read(rm, REG_CHAN_FAULT, &chan); + regmap_read(rm, REG_GLOBAL_FAULT1, &global1); + regmap_read(rm, REG_GLOBAL_FAULT2, &global2); + + dev_dbg(component->dev, "fault regs: CHAN=3D%02x, " + "GLOBAL1=3D%02x, GLOBAL2=3D%02x\n", + chan, global1, global2); + + regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ); + } + mutex_unlock(&tas5805m->lock); } =20 return 0; @@ -354,7 +391,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_m= ap[] =3D { =20 static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] =3D { SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, + tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_OUTPUT("OUT") }; =20 @@ -375,11 +413,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int= mute, int direction) struct tas5805m_priv *tas5805m =3D snd_soc_component_get_drvdata(component); =20 + mutex_lock(&tas5805m->lock); dev_dbg(component->dev, "set mute=3D%d (is_powered=3D%d)\n", mute, tas5805m->is_powered); + tas5805m->is_muted =3D mute; if (tas5805m->is_powered) - tas5805m_refresh(component); + tas5805m_refresh(tas5805m); + mutex_unlock(&tas5805m->lock); =20 return 0; } @@ -434,6 +475,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) if (!tas5805m) return -ENOMEM; =20 + tas5805m->i2c =3D i2c; tas5805m->pvdd =3D devm_regulator_get(dev, "pvdd"); if (IS_ERR(tas5805m->pvdd)) { dev_err(dev, "failed to get pvdd supply: %ld\n", @@ -507,6 +549,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) gpiod_set_value(tas5805m->gpio_pdn_n, 1); usleep_range(10000, 15000); =20 + INIT_WORK(&tas5805m->work, do_work); + mutex_init(&tas5805m->lock); + /* Don't register through devm. We need to be able to unregister * the component prior to deasserting PDN# */ @@ -527,6 +572,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c) struct device *dev =3D &i2c->dev; struct tas5805m_priv *tas5805m =3D dev_get_drvdata(dev); =20 + cancel_work_sync(&tas5805m->work); snd_soc_unregister_component(dev); gpiod_set_value(tas5805m->gpio_pdn_n, 0); usleep_range(10000, 15000); --=20 2.38.1 From nobody Sat Sep 13 06:14:49 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 960BCC636CD for ; Sat, 4 Feb 2023 21:02:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233085AbjBDVCP (ORCPT ); Sat, 4 Feb 2023 16:02:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232417AbjBDVCL (ORCPT ); Sat, 4 Feb 2023 16:02:11 -0500 Received: from mail-pg1-x531.google.com (mail-pg1-x531.google.com [IPv6:2607:f8b0:4864:20::531]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EEA6620D00 for ; Sat, 4 Feb 2023 13:02:10 -0800 (PST) Received: by mail-pg1-x531.google.com with SMTP id a23so5835254pga.13 for ; Sat, 04 Feb 2023 13:02:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=igorinstitute-com.20210112.gappssmtp.com; s=20210112; h=cc:to:subject:date:from:references:in-reply-to:message-id:from:to :cc:subject:date:message-id:reply-to; bh=Iy74VsRO4WDPI6duqo1jqOxf/w5vgZYHdL8GT2SYMKg=; b=3w2YiAyNJtEQDGuv+q7PteQbxAc90iPxEhXnUrO3pypsg9+j3VEF6mDjcBvK2d6wcS HIA47XOx8JQMCuEL9QMqJ6ePxyG6xNYxnP6Ua5JnkAMN2wiu+gUpM+ZThpofkVWVfAlj T7RepGAQshvpe0Q59PUc5VTkj08UpWL71psGPVyphDalykOLecEuf+dN+mkjzPgvMyT0 dTroAiVxWHhwN+qDjQzIdL7wAyfGoI3xNZ6w6gGOesYEgD+RNS+YpVorOx1SH+fOeBVH vbi4W0huTNQ4wLDgJsHnjsgY+aPSfXYhBT9yWQfwmkZCNighdfNn+seKdpZvO39nN+8U K7Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:date:from:references:in-reply-to:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Iy74VsRO4WDPI6duqo1jqOxf/w5vgZYHdL8GT2SYMKg=; b=GdRGJDf21j84N2Fvbb/dCv0XiLZ6ZCU6GTYTw1Idsn6I8qSuLYlY1pD5ybblILUqUJ +i1lTl84Oy6Lz15qlwh9lHnNB/w8F9z99ZQL7RtcFRcO5lv4kb4QCY5jU23cn2niiLyV QzlSi3BaFZ+H+K8JV5AsLQdqYTlxcz8HIy7FaAtnRlNNuJz8uiL95uBMUeR08Up8iVJ9 3ng+40L9cfFcqyOO+WfqH7uaQ+7SLFanNjlCvQCKrt6PMi+ePBRZ8Fc3C194XV4ROfb0 afRAjylL9bTXXzi9vF9HLrCsUa7qLgwtL84uh4XqOlwZJ3eX/Xh1hMwmbBcFW0jOXeld mMQQ== X-Gm-Message-State: AO0yUKVApc3DUuM8bbg1lm+IFB6bupqVFqE8FXeBBGMGiNt6OSb2nJFT GwQHBXaxkGUsb7x0LkNL+YpGvymcAiWp52zY X-Google-Smtp-Source: AK7set/RHBlFpv8T3OLVL5wC59M32m9IYL76JHfQskGRevwysuhNbGGfCrdmUEkCXh5ukykwH4hIhQ== X-Received: by 2002:a05:6a00:c87:b0:593:af2e:b872 with SMTP id a7-20020a056a000c8700b00593af2eb872mr17898882pfv.2.1675544530517; Sat, 04 Feb 2023 13:02:10 -0800 (PST) Received: from localhost ([121.99.145.49]) by smtp.gmail.com with ESMTPSA id h30-20020a056a00001e00b0058bbaa5200dsm4106116pfk.214.2023.02.04.13.02.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 04 Feb 2023 13:02:10 -0800 (PST) Message-Id: <1fea38a71ea6ab0225d19ab28d1fa12828d762d0.1675497326.git.daniel.beer@igorinstitute.com> In-Reply-To: References: From: Daniel Beer Date: Thu, 27 Oct 2022 21:38:38 +1300 Subject: [PATCH v3 2/2] ASoC: tas5805m: add missing page switch. To: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org, Daniel Beer , Andy Liu , Mark Brown Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In tas5805m_refresh, we switch pages to update the DSP volume control, but we need to switch back to page 0 before trying to alter the soft-mute control. This latter page-switch was missing. Fixes: ec45268467f4 ("ASoC: add support for TAS5805M digital amplifier") Signed-off-by: Daniel Beer --- sound/soc/codecs/tas5805m.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index 6e2edf045446..4e38eb7acea1 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -203,6 +203,9 @@ static void tas5805m_refresh(struct tas5805m_priv *tas5= 805m) set_dsp_scale(rm, 0x24, tas5805m->vol[0]); set_dsp_scale(rm, 0x28, tas5805m->vol[1]); =20 + regmap_write(rm, REG_PAGE, 0x00); + regmap_write(rm, REG_BOOK, 0x00); + /* Set/clear digital soft-mute */ regmap_write(rm, REG_DEVICE_CTRL_2, (tas5805m->is_muted ? DCTRL2_MUTE : 0) | --=20 2.38.1