Received: by 2002:a05:6358:9144:b0:117:f937:c515 with SMTP id r4csp3742184rwr; Sun, 7 May 2023 19:10:51 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6KuCGIsMoXWs/knOu0/drLFevRm36n8zSujm6lnw2C45jed6eeFqqf4P0acrXrTF5vU13H X-Received: by 2002:a05:6a00:98a:b0:643:85a0:57fe with SMTP id u10-20020a056a00098a00b0064385a057femr13839317pfg.2.1683511851172; Sun, 07 May 2023 19:10:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683511851; cv=none; d=google.com; s=arc-20160816; b=NI1uRDmK/jqvtEYdylmKVBnsGSNWOfOUMzcAqZDtcD4Ml8elh7bgvnLq/hZVBppVY3 o1cGlruy51vFuQBy8FkZEFpfAeK87fMOSChCUv71w6ABZyL30ryafhuTfpIfrTn/hnfW ZLkcXnnElH1pMc2OHVhuwM2azUo7uRsuuUlwEdhPF5/I3PF8ycZIqNhO7ctbGFbj5mB5 5kCwXQ8mgDVlv5NI0OqkfvBOu6JZeUNOOa3586VrPHUSkkii/P9620rOabRMH1CGA5bU wexEd6Ya53SY2h2qFNlV9ZgZSO8qTnnElxSw47cC11DBOcRH669x9ulFkx+wbTAVTaEl 35hQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :content-language:references:cc:to:subject:user-agent:mime-version :date:message-id; bh=SIiWcvo2tSJqjM0xd5pDLdV2xqc9lv5noEG3vx/B4D8=; b=lq6BXAJzJHnz2c9uTJcVbgQ04Xl9N6jhLnTFBO5k6/ry0MDIWGc3+PL+UxOGaSTN6m 6vl6mSe6/dx1lt6SwSaJGbSF2VbxRKOMZmEQpfJa83IqeWuNxnqFtpO73JYAF71gCdA0 rF+zSGkRHCchflXOmFVgZTR5p0g1yrh6T4eXNQQbvpMqX2jHXOZg0noQnOH5HW8tBiDc 9CdibFqV3DRiAIMYNIhdsyJnTlzQ9BcwI7f9wrGSefPKEJnSZdxQt2hoR6n0clVx4Qhs hCywlo0hyywH4QI2uuzquEybUULFQHlJqbCec2gNDrmrqewbda1gT6qTfbTk1LEd2rvr u3cw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i15-20020a056a00004f00b00625c6092a12si4092802pfk.215.2023.05.07.19.10.39; Sun, 07 May 2023 19:10:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232098AbjEHBlz convert rfc822-to-8bit (ORCPT + 99 others); Sun, 7 May 2023 21:41:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229662AbjEHBly (ORCPT ); Sun, 7 May 2023 21:41:54 -0400 Received: from ex01.ufhost.com (ex01.ufhost.com [61.152.239.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B5217DBB; Sun, 7 May 2023 18:41:49 -0700 (PDT) Received: from EXMBX166.cuchost.com (unknown [175.102.18.54]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "EXMBX166", Issuer "EXMBX166" (not verified)) by ex01.ufhost.com (Postfix) with ESMTP id 3505F24E03C; Mon, 8 May 2023 09:41:33 +0800 (CST) Received: from EXMBX168.cuchost.com (172.16.6.78) by EXMBX166.cuchost.com (172.16.6.76) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Mon, 8 May 2023 09:41:33 +0800 Received: from [192.168.125.124] (183.27.98.219) by EXMBX168.cuchost.com (172.16.6.78) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Mon, 8 May 2023 09:41:32 +0800 Message-ID: <622746ca-8d29-72cf-cc8f-cfe7bc5aea58@starfivetech.com> Date: Mon, 8 May 2023 09:41:31 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.10.1 Subject: Re: [PATCH v3 2/3] ASoC: starfive: Add JH7110 TDM driver To: Shengyu Qu , Mark Brown , "Liam Girdwood" , Jaroslav Kysela , "Takashi Iwai" , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Emil Renner Berthing CC: , , , References: <20230506090116.9206-1-walker.chen@starfivetech.com> <20230506090116.9206-3-walker.chen@starfivetech.com> Content-Language: en-US From: Walker Chen In-Reply-To: Content-Type: text/plain; charset="UTF-8" X-Originating-IP: [183.27.98.219] X-ClientProxiedBy: EXCAS064.cuchost.com (172.16.6.24) To EXMBX168.cuchost.com (172.16.6.78) X-YovoleRuleAgent: yovoleflag Content-Transfer-Encoding: 8BIT X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00,NICE_REPLY_A, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2023/5/6 21:47, Shengyu Qu wrote: > Hi, > >> Add tdm driver support for the StarFive JH7110 SoC. >> >> Signed-off-by: Walker Chen >> --- >>   MAINTAINERS                     |   6 + >>   sound/soc/Kconfig               |   1 + >>   sound/soc/Makefile              |   1 + >>   sound/soc/starfive/Kconfig      |  15 + >>   sound/soc/starfive/Makefile     |   2 + >>   sound/soc/starfive/jh7110_tdm.c | 573 ++++++++++++++++++++++++++++++++ >>   sound/soc/starfive/jh7110_tdm.h | 147 ++++++++ >>   7 files changed, 745 insertions(+) >>   create mode 100644 sound/soc/starfive/Kconfig >>   create mode 100644 sound/soc/starfive/Makefile >>   create mode 100644 sound/soc/starfive/jh7110_tdm.c >>   create mode 100644 sound/soc/starfive/jh7110_tdm.h >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index 5f9c544bc189..add89615d327 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -19945,6 +19945,12 @@ F:    Documentation/devicetree/bindings/power/starfive* >>   F:    drivers/soc/starfive/jh71xx_pmu.c >>   F:    include/dt-bindings/power/starfive,jh7110-pmu.h >>   +STARFIVE JH7110 TDM DRIVERS >> +M:    Walker Chen >> +S:    Maintained >> +F:    Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml >> +F:    sound/soc/starfive/jh7110-tdm.* >> + >>   STARFIVE SOC DRIVERS >>   M:    Conor Dooley >>   S:    Maintained >> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig >> index 848fbae26c3b..8d1d9401ecf2 100644 >> --- a/sound/soc/Kconfig >> +++ b/sound/soc/Kconfig >> @@ -91,6 +91,7 @@ source "sound/soc/sh/Kconfig" >>   source "sound/soc/sof/Kconfig" >>   source "sound/soc/spear/Kconfig" >>   source "sound/soc/sprd/Kconfig" >> +source "sound/soc/starfive/Kconfig" >>   source "sound/soc/sti/Kconfig" >>   source "sound/soc/stm/Kconfig" >>   source "sound/soc/sunxi/Kconfig" >> diff --git a/sound/soc/Makefile b/sound/soc/Makefile >> index 507eaed1d6a1..65aeb4ef4068 100644 >> --- a/sound/soc/Makefile >> +++ b/sound/soc/Makefile >> @@ -59,6 +59,7 @@ obj-$(CONFIG_SND_SOC)    += sh/ >>   obj-$(CONFIG_SND_SOC)    += sof/ >>   obj-$(CONFIG_SND_SOC)    += spear/ >>   obj-$(CONFIG_SND_SOC)    += sprd/ >> +obj-$(CONFIG_SND_SOC)    += starfive/ >>   obj-$(CONFIG_SND_SOC)    += sti/ >>   obj-$(CONFIG_SND_SOC)    += stm/ >>   obj-$(CONFIG_SND_SOC)    += sunxi/ >> diff --git a/sound/soc/starfive/Kconfig b/sound/soc/starfive/Kconfig >> new file mode 100644 >> index 000000000000..737c956f7b93 >> --- /dev/null >> +++ b/sound/soc/starfive/Kconfig >> @@ -0,0 +1,15 @@ >> +# SPDX-License-Identifier: GPL-2.0-only >> +config SND_SOC_STARFIVE >> +    tristate "Audio support for StarFive SoC" >> +    depends on COMPILE_TEST || SOC_STARFIVE >> +    help >> +      Say Y or M if you want to add support for codecs attached to >> +      the Starfive SoCs' Audio interfaces. You will also need to >> +      select the audio interfaces to support below. >> + >> +config SND_SOC_JH7110_TDM >> +    tristate "JH7110 TDM device driver" >> +    depends on HAVE_CLK && SND_SOC_STARFIVE >> +    select SND_SOC_GENERIC_DMAENGINE_PCM >> +    help >> +      Say Y or M if you want to add support for StarFive TDM driver. >> diff --git a/sound/soc/starfive/Makefile b/sound/soc/starfive/Makefile >> new file mode 100644 >> index 000000000000..f7d960211d72 >> --- /dev/null >> +++ b/sound/soc/starfive/Makefile >> @@ -0,0 +1,2 @@ >> +# StarFive Platform Support >> +obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o >> diff --git a/sound/soc/starfive/jh7110_tdm.c b/sound/soc/starfive/jh7110_tdm.c >> new file mode 100644 >> index 000000000000..33f7cf43e4bd >> --- /dev/null >> +++ b/sound/soc/starfive/jh7110_tdm.c >> @@ -0,0 +1,573 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * jh7110_tdm.c -- StarFive JH7110 TDM driver >> + * >> + * Copyright (C) 2022-2023 StarFive Technology Co., Ltd. >> + * >> + * Author: Walker Chen >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include "jh7110_tdm.h" >> + >> +static inline u32 jh7110_tdm_readl(struct jh7110_tdm_dev *tdm, u16 reg) >> +{ >> +    return readl_relaxed(tdm->tdm_base + reg); >> +} >> + >> +static inline void jh7110_tdm_writel(struct jh7110_tdm_dev *tdm, u16 reg, u32 val) >> +{ >> +    writel_relaxed(val, tdm->tdm_base + reg); >> +} >> + >> +static void jh7110_tdm_save_context(struct jh7110_tdm_dev *tdm, >> +                    struct snd_pcm_substream *substream) >> +{ >> +    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) >> +        tdm->saved_pcmtxcr = jh7110_tdm_readl(tdm, TDM_PCMTXCR); >> +    else >> +        tdm->saved_pcmrxcr = jh7110_tdm_readl(tdm, TDM_PCMRXCR); >> +} >> + >> +static void jh7110_tdm_start(struct jh7110_tdm_dev *tdm, >> +                 struct snd_pcm_substream *substream) >> +{ >> +    u32 data; >> + >> +    data = jh7110_tdm_readl(tdm, TDM_PCMGBCR); >> +    jh7110_tdm_writel(tdm, TDM_PCMGBCR, data | PCMGBCR_ENABLE); >> + >> +    /* restore context */ >> +    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) >> +        jh7110_tdm_writel(tdm, TDM_PCMTXCR, tdm->saved_pcmtxcr | PCMTXCR_TXEN); >> +    else >> +        jh7110_tdm_writel(tdm, TDM_PCMRXCR, tdm->saved_pcmrxcr | PCMRXCR_RXEN); >> +} >> + >> +static void jh7110_tdm_stop(struct jh7110_tdm_dev *tdm, >> +                struct snd_pcm_substream *substream) >> +{ >> +    unsigned int val; >> + >> +    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { >> +        val = jh7110_tdm_readl(tdm, TDM_PCMTXCR); >> +        val &= ~PCMTXCR_TXEN; >> +        jh7110_tdm_writel(tdm, TDM_PCMTXCR, val); >> +    } else { >> +        val = jh7110_tdm_readl(tdm, TDM_PCMRXCR); >> +        val &= ~PCMRXCR_RXEN; >> +        jh7110_tdm_writel(tdm, TDM_PCMRXCR, val); >> +    } >> +} >> + >> +static int jh7110_tdm_syncdiv(struct jh7110_tdm_dev *tdm) >> +{ >> +    u32 sl, sscale, syncdiv; >> + >> +    if (tdm->rx.sl >= tdm->tx.sl) >> +        sl = tdm->rx.sl; >> +    else >> +        sl = tdm->tx.sl; >> + >> +    if (tdm->rx.sscale >= tdm->tx.sscale) >> +        sscale = tdm->rx.sscale; >> +    else >> +        sscale = tdm->tx.sscale; >> + >> +    syncdiv = tdm->pcmclk / tdm->samplerate - 1; >> + >> +    if ((syncdiv + 1) < (sl * sscale)) { >> +        dev_err(tdm->dev, "Failed to set syncdiv!\n"); >> +        return -EINVAL; >> +    } >> + >> +    if (tdm->syncm == TDM_SYNCM_LONG && >> +        (tdm->rx.sscale <= 1 || tdm->tx.sscale <= 1)) { >> +        if ((syncdiv + 1) <= sl) { >> +            dev_err(tdm->dev, "Wrong syncdiv! It must be (syncdiv+1) > max[tx.sl, rx.sl]\n"); >> +            return -EINVAL; >> +        } >> +    } >> + >> +    jh7110_tdm_writel(tdm, TDM_PCMDIV, syncdiv); >> +    return 0; >> +} >> + >> +static int jh7110_tdm_config(struct jh7110_tdm_dev *tdm, >> +                 struct snd_pcm_substream *substream) >> +{ >> +    u32 datarx, datatx; >> +    int ret; >> + >> +    ret = jh7110_tdm_syncdiv(tdm); >> +    if (ret) >> +        return ret; >> + >> +    datarx = (tdm->rx.ifl << IFL_BIT) | >> +          (tdm->rx.wl << WL_BIT) | >> +          (tdm->rx.sscale << SSCALE_BIT) | >> +          (tdm->rx.sl << SL_BIT) | >> +          (tdm->rx.lrj << LRJ_BIT); >> + >> +    datatx = (tdm->tx.ifl << IFL_BIT) | >> +          (tdm->tx.wl << WL_BIT) | >> +          (tdm->tx.sscale << SSCALE_BIT) | >> +          (tdm->tx.sl << SL_BIT) | >> +          (tdm->tx.lrj << LRJ_BIT); >> + >> +    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) >> +        jh7110_tdm_writel(tdm, TDM_PCMTXCR, datatx); >> +    else >> +        jh7110_tdm_writel(tdm, TDM_PCMRXCR, datarx); >> + >> +    return 0; >> +} >> + >> +static void jh7110_tdm_clk_disable(struct jh7110_tdm_dev *tdm) >> +{ >> +    int i; >> + >> +    for (i = tdm->num_clks - 1; i >= 0; i--) >> +        clk_disable_unprepare(tdm->clks[i]); >> +} >> + >> +static int jh7110_tdm_clk_enable(struct jh7110_tdm_dev *tdm) >> +{ >> +    int i, ret; >> + >> +    for (i = 0; i < tdm->num_clks; i++) { >> +        ret = clk_prepare_enable(tdm->clks[i]); >> +        if (ret) { >> +            while (i-- > 0) >> +                clk_disable_unprepare(tdm->clks[i]); >> +            return ret; >> +        } >> +    } >> + >> +    ret = reset_control_deassert(tdm->resets); >> +    if (ret) { >> +        dev_err(tdm->dev, "Failed to deassert tdm resets\n"); >> +        goto dis_tdm_clk; >> +    } >> + >> +    /* select tdm_ext clock as the clock source for tdm */ >> +    ret = clk_set_parent(tdm->clks[5], tdm->clks[4]); >> +    if (ret) { >> +        dev_err(tdm->dev, "Can't set clock source for clk_tdm: %d\n", ret); >> +        goto dis_tdm_clk; >> +    } >> +    return 0; >> + >> +dis_tdm_clk: >> +    for (i = tdm->num_clks - 1; i >= 0; i--) >> +        clk_disable_unprepare(tdm->clks[i]); >> + >> +    return ret; >> +} >> + >> +#ifdef CONFIG_PM >> +static int jh7110_tdm_runtime_suspend(struct device *dev) >> +{ >> +    struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); >> + >> +    jh7110_tdm_clk_disable(tdm); >> +    return 0; >> +} >> + >> +static int jh7110_tdm_runtime_resume(struct device *dev) >> +{ >> +    struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); >> + >> +    return jh7110_tdm_clk_enable(tdm); >> +} >> +#endif >> + >> +#ifdef CONFIG_PM_SLEEP >> +static int jh7110_tdm_suspend(struct snd_soc_component *component) >> +{ >> +    /* save context */ >> +    tdm->saved_pcmgbcr = jh7110_tdm_readl(tdm, TDM_PCMGBCR); >> +    tdm->saved_pcmdiv = jh7110_tdm_readl(tdm, TDM_PCMDIV); > > tdm isn't declared here. Is that same with resume function? OMG! Maybe I accidentally deleted the declaration of tdm while deleting some debugging statement. Yes, it is same with resume function. Best regards, Walker