From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81CC670 for ; Sun, 1 Aug 2021 09:47:57 +0000 (UTC) Received: by mail-pl1-f178.google.com with SMTP id u2so8024538plg.10 for ; Sun, 01 Aug 2021 02:47:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=L4zxM4cwYaEtb0LsuZc0Nq6yIU8PNzb7rVpdAyyjN3Qz09GTkRmqaJG7oKR4dxaWU6 hlwNuK8q11HeOlO7HMBlY7wOrB3Nsh15pIBdar7tyI7bF8asV+tbIq9Jj33r47HuyhRH IOOwlZNlaCV0D10goupNP4TADB/zlHqgo38lYguc64Ns7kaITpqaPlCxHdek9MdIH70v xjFAmQlprOBa4hvfclEmvN2iAWEAjA2VpvQqe6wo/pOFmImHCW1BKJiHUqTYiUbJYlKj 37b5KDgLrWHkk+jYHoKleLNbHCvfF9hcTjZzksPJteti//b61nH8uCC94nx6Le3kwgrL nBoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=AVhFSBF0t/nJ6ma/Hjrt/GM9X9sIqjwp3wYb0mdwYSLqFUwxKLKvUc9lI2x7tSF1mP cNo3D0K2fQGtg5tSlTNIx2gAlYRqmLzbo79znjOL2DYUlWTUN+Fg3IEKBjOx7icbKL3H LHycvj0NfzJiy5T5jrjPYeUiCz/n3DZVtzn/k05DZtBf+WcVo+tizQACfwiIB9zLSQFF Aa6r/SHkTweO6CfP/9cuILb4QoNauWPzSEm6QAHSGKTprMx5ChAr7rqUpM/ax1MzYznt 5QZMfxFb4ArsFMWYlu1MKKmnmsoRDJJafr0y0z+8ec4+T3i2RGZvXcRw3J4IJmQCnfD2 ZMeg== X-Gm-Message-State: AOAM533zrZ0ufk27Fuu3PL2hCI3BfWeReDJhYI6F7g8DgEOGQICKxZrn y4bQjagFym9jN7lV8wIQOn/ypdtGjbA9hPVNCg== X-Google-Smtp-Source: ABdhPJw+tr2GBOalJTQGoLDnu3vIb3xXi8UtX9Wb7GNDzZbodvVLRBmN/5cJrIfzRPYkc98i2oWEtJMoD7pd10Yhytk= X-Received: by 2002:a62:4e0f:0:b029:329:20be:287a with SMTP id c15-20020a624e0f0000b029032920be287amr11522272pfb.55.1627811276782; Sun, 01 Aug 2021 02:47:56 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 References: <20210711122055.4529-1-fengzheng923@gmail.com> <20210715074750.ewbggulc5kast6ez@gilmour> In-Reply-To: <20210715074750.ewbggulc5kast6ez@gilmour> From: =?UTF-8?B?54+t5rab?= Date: Sun, 1 Aug 2021 17:47:46 +0800 Message-ID: Subject: Re: [PATCH v6 1/2] ASoC: sunxi: Add Allwinner H6 Digital MIC driver To: Maxime Ripard Cc: lgirdwood@gmail.com, Mark Brown , perex@perex.cz, tiwai@suse.com, wens@csie.org, jernej.skrabec@gmail.com, p.zabel@pengutronix.de, Samuel Holland , krzk@kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, Dear: Maxime Ripard =E4=BA=8E2021=E5=B9=B47=E6=9C=8815=E6=97= =A5=E5=91=A8=E5=9B=9B =E4=B8=8B=E5=8D=883:47=E5=86=99=E9=81=93=EF=BC=9A > > Hi > > On Sun, Jul 11, 2021 at 08:20:55AM -0400, fengzheng923@gmail.com wrote: > > From: Ban Tao > > > > The Allwinner H6 and later SoCs have an DMIC block > > which is capable of capture. > > > > Signed-off-by: Ban Tao > > > > --- > > v1->v2: > > 1.Fix some compilation errors. > > 2.Modify some code styles. > > --- > > v2->v3: > > None. > > --- > > v3->v4: > > 1.add sig_bits. > > --- > > v4->v5: > > None. > > --- > > v5->v6: > > 1.Modify RXFIFO_CTL_MODE to mode 1. > > --- > > MAINTAINERS | 7 + > > sound/soc/sunxi/Kconfig | 8 + > > sound/soc/sunxi/Makefile | 1 + > > sound/soc/sunxi/sun50i-dmic.c | 403 ++++++++++++++++++++++++++++++++++ > > 4 files changed, 419 insertions(+) > > create mode 100644 sound/soc/sunxi/sun50i-dmic.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index e924f9e5df97..8d700baaa3ca 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -760,6 +760,13 @@ L: linux-media@vger.kernel.org > > S: Maintained > > F: drivers/staging/media/sunxi/cedrus/ > > > > +ALLWINNER DMIC DRIVERS > > +M: Ban Tao > > +L: alsa-devel@alsa-project.org (moderated for non-subscribers) > > +S: Maintained > > +F: Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.= yaml > > +F: sound/soc/sunxi/sun50i-dmic.c > > + > > ALPHA PORT > > M: Richard Henderson > > M: Ivan Kokshaysky > > diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig > > index ddcaaa98d3cb..2a3bf7722e11 100644 > > --- a/sound/soc/sunxi/Kconfig > > +++ b/sound/soc/sunxi/Kconfig > > @@ -56,6 +56,14 @@ config SND_SUN4I_SPDIF > > Say Y or M to add support for the S/PDIF audio block in the All= winner > > A10 and affiliated SoCs. > > > > +config SND_SUN50I_DMIC > > + tristate "Allwinner H6 DMIC Support" > > + depends on (OF && ARCH_SUNXI) || COMPILE_TEST > > + select SND_SOC_GENERIC_DMAENGINE_PCM > > + help > > + Say Y or M to add support for the DMIC audio block in the Allwi= nner > > + H6 and affiliated SoCs. > > + > > config SND_SUN8I_ADDA_PR_REGMAP > > tristate > > select REGMAP > > diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile > > index a86be340a076..4483fe9c94ef 100644 > > --- a/sound/soc/sunxi/Makefile > > +++ b/sound/soc/sunxi/Makefile > > @@ -6,3 +6,4 @@ obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) +=3D sun8i-codec-a= nalog.o > > obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) +=3D sun50i-codec-analog.o > > obj-$(CONFIG_SND_SUN8I_CODEC) +=3D sun8i-codec.o > > obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) +=3D sun8i-adda-pr-regmap.o > > +obj-$(CONFIG_SND_SUN50I_DMIC) +=3D sun50i-dmic.o > > diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmi= c.c > > new file mode 100644 > > index 000000000000..bbac836ba4de > > --- /dev/null > > +++ b/sound/soc/sunxi/sun50i-dmic.c > > @@ -0,0 +1,403 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +// > > +// This driver supports the DMIC in Allwinner's H6 SoCs. > > +// > > +// Copyright 2021 Ban Tao > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define SUN50I_DMIC_EN_CTL (0x00) > > + #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8) > > + #define SUN50I_DMIC_EN_CTL_CHAN(v) ((v) << 0) > > + #define SUN50I_DMIC_EN_CTL_CHAN_MASK GENMASK(7, 0) > > +#define SUN50I_DMIC_SR (0x04) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE(v) ((v) << 0) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CTL (0x08) > > + #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE BIT(0) > > +#define SUN50I_DMIC_DATA (0x10) > > +#define SUN50I_DMIC_INTC (0x14) > > + #define SUN50I_DMIC_FIFO_DRQ_EN BIT(2) > > +#define SUN50I_DMIC_INT_STA (0x18) > > + #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING BIT(1) > > + #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING BIT(0) > > +#define SUN50I_DMIC_RXFIFO_CTL (0x1c) > > + #define SUN50I_DMIC_RXFIFO_CTL_FLUSH BIT(31) > > + #define SUN50I_DMIC_RXFIFO_CTL_MODE BIT(9) > > + #define SUN50I_DMIC_RXFIFO_CTL_RESOLUTION BIT(8) > > +#define SUN50I_DMIC_CH_NUM (0x24) > > + #define SUN50I_DMIC_CH_NUM_N(v) ((v) << 0) > > + #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CNT (0x2c) > > + #define SUN50I_DMIC_CNT_N BIT(0) > > +#define SUN50I_DMIC_HPF_CTRL (0x38) > > +#define SUN50I_DMIC_VERSION (0x50) > > + > > + > > There's multiple blank lines here > > > +struct sun50i_dmic_dev { > > + struct clk *dmic_clk; > > + struct clk *bus_clk; > > + struct reset_control *rst; > > + struct regmap *regmap; > > + struct snd_dmaengine_dai_dma_data dma_params_rx; > > + unsigned int chan_en; > > +}; > > + > > +struct dmic_rate { > > + unsigned int samplerate; > > + unsigned int rate_bit; > > +}; > > + > > +static int sun50i_dmic_startup(struct snd_pcm_substream *substream, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + struct snd_soc_pcm_runtime *rtd =3D substream->private_data; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(asoc_rtd= _to_cpu(rtd, 0)); > > + > > + /* only support capture */ > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH); > > + regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream, > > + struct snd_pcm_hw_params *params, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + int i =3D 0; > > + unsigned long rate =3D params_rate(params); > > + unsigned int mclk =3D 0; > > + unsigned int channels =3D params_channels(params); > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(cpu_dai)= ; > > + static struct dmic_rate dmic_rate_s[] =3D { > > + {44100, 0x0}, > > + {48000, 0x0}, > > + {22050, 0x2}, > > + {24000, 0x2}, > > + {11025, 0x4}, > > + {12000, 0x4}, > > + {32000, 0x1}, > > + {16000, 0x3}, > > + {8000, 0x5}, > > + }; > > We should order these items. It looks like descending rate makes the > most sense? > > Also, I'm not sure why we need to make that array local, can't this be a > global variable? > > > + /* DMIC num is N+1 */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM, > > + SUN50I_DMIC_CH_NUM_N_MASK, > > + SUN50I_DMIC_CH_NUM_N(channels - 1)); > > + host->chan_en =3D (1 << channels) - 1; > > + regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, host->chan_en); > > Do we need to store the channels bitmask in the main structure? It looks > fairly easy to generate, so I guess we could just use a macro I need to store channels bitmask and use it in sun50i_dmic_trigger function= . > > > + switch (params_format(params)) { > > + case SNDRV_PCM_FORMAT_S16_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, 0); > > + break; > > + case SNDRV_PCM_FORMAT_S24_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION); > > + break; > > These two defines could be named a bit better, it's not really clear > what SUN50I_DMIC_RXFIFO_CTL_RESOLUTION means, exactly, as opposed to 0 > (while it's actually the sample width). > > What about something like SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16 (for 0) and > _24 (for 1), while changing SUN50I_DMIC_RXFIFO_CTL_RESOLUTION for > SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK ? > > > + default: > > + dev_err(cpu_dai->dev, "Invalid format!\n"); > > + return -EINVAL; > > + } > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_MODE, > > + SUN50I_DMIC_RXFIFO_CTL_MODE); > > Same thing here, MODE doesn't really explain what this does, and why > we'd want to always set it. > > I guess 0 is LSB_ZERO and 1 is MSB_SIGN? Yes. > > > + switch (rate) { > > + case 11025: > > + case 22050: > > + case 44100: > > + mclk =3D 22579200; > > + break; > > + case 8000: > > + case 12000: > > + case 16000: > > + case 24000: > > + case 32000: > > + case 48000: > > + mclk =3D 24576000; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Invalid rate!\n"); > > + return -EINVAL; > > + } > > + > > + if (clk_set_rate(host->dmic_clk, mclk)) { > > + dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk); > > + return -EINVAL; > > + } > > + > > + for (i =3D 0; i < ARRAY_SIZE(dmic_rate_s); i++) { > > + if (dmic_rate_s[i].samplerate =3D=3D rate) { > > + regmap_update_bits(host->regmap, SUN50I_DMIC_SR, > > + SUN50I_DMIC_SR_SAMPLE_RATE_MAS= K, > > + SUN50I_DMIC_SR_SAMPLE_RATE(dmi= c_rate_s[i].rate_bit)); > > + break; > > + } > > + } > > + > > + switch (params_physical_width(params)) { > > + case 16: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_2_B= YTES; > > + break; > > + case 32: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_4_B= YTES; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Unsupported physical sample width:= %d\n", > > + params_physical_width(params)); > > + return -EINVAL; > > + } > > + > > + /* oversamplerate adjust */ > > + if (params_rate(params) >=3D 24000) > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE); > > + else > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, in= t cmd, > > + struct snd_soc_dai *dai) > > +{ > > + int ret =3D 0; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + switch (cmd) { > > + case SNDRV_PCM_TRIGGER_START: > > + case SNDRV_PCM_TRIGGER_RESUME: > > + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > > + /* DRQ ENABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, > > + SUN50I_DMIC_FIFO_DRQ_EN); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(host->chan_en)= ); > > + /* Global enable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, > > + SUN50I_DMIC_EN_CTL_GLOBE); > > + break; > > Do we really need to clear the channel and global enable bits? and DRQ? Why not? I think we should clear them when not in use...... > > > + case SNDRV_PCM_TRIGGER_STOP: > > + case SNDRV_PCM_TRIGGER_SUSPEND: > > + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: > > + /* DRQ DISABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, 0); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(0)); > > + /* Global disable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, 0); > > + break; > > + > > + default: > > + ret =3D -EINVAL; > > + break; > > + } > > + return ret; > > +} > > + > > +static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai) > > +{ > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx); > > + > > + return 0; > > +} > > + > > +static const struct snd_soc_dai_ops sun50i_dmic_dai_ops =3D { > > + .startup =3D sun50i_dmic_startup, > > + .trigger =3D sun50i_dmic_trigger, > > + .hw_params =3D sun50i_dmic_hw_params, > > +}; > > + > > +static const struct regmap_config sun50i_dmic_regmap_config =3D { > > + .reg_bits =3D 32, > > + .reg_stride =3D 4, > > + .val_bits =3D 32, > > + .max_register =3D SUN50I_DMIC_VERSION, > > + .cache_type =3D REGCACHE_NONE, > > +}; > > + > > +#define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000) > > +#define SUN50I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTB= IT_S24_LE) > > SUN50I_DMIC_RATES has a tab between the define and its name, while > SUN50I_FORMATS has the tab after the name. We should be consistent. > Similarly, we should name both with the SUN50I_DMIC prefix. > > > +static struct snd_soc_dai_driver sun50i_dmic_dai =3D { > > + .capture =3D { > > + .channels_min =3D 1, > > + .channels_max =3D 8, > > + .rates =3D SUN50I_DMIC_RATES, > > + .formats =3D SUN50I_FORMATS, > > + .sig_bits =3D 21, > > + }, > > + .probe =3D sun50i_dmic_soc_dai_probe, > > + .ops =3D &sun50i_dmic_dai_ops, > > + .name =3D "dmic", > > +}; > > + > > +static const struct of_device_id sun50i_dmic_of_match[] =3D { > > + { > > + .compatible =3D "allwinner,sun50i-h6-dmic", > > + }, > > + { /* sentinel */ } > > +}; > > +MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match); > > + > > +static const struct snd_soc_component_driver sun50i_dmic_component =3D= { > > + .name =3D "sun50i-dmic", > > +}; > > + > > +static int sun50i_dmic_runtime_suspend(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + > > + clk_disable_unprepare(host->dmic_clk); > > + clk_disable_unprepare(host->bus_clk); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_runtime_resume(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + int ret; > > + > > + ret =3D clk_prepare_enable(host->dmic_clk); > > + if (ret) > > + return ret; > > A new line here would be great. > > > + ret =3D clk_prepare_enable(host->bus_clk); > > + if (ret) > > + clk_disable_unprepare(host->dmic_clk); > > + > > + return ret; > > In general we prefer to treat the error path and the success path > differently. In this case it would mean changing that part to > > ret =3D clk_prepare_enable(host->bus_clk); > if (ret) { > clk_disable_unprepare(host->dmic_clk); > return ret; > } > > return 0; > > > +} > > + > > +static int sun50i_dmic_probe(struct platform_device *pdev) > > +{ > > + struct sun50i_dmic_dev *host; > > + struct resource *res; > > + int ret; > > + void __iomem *base; > > + > > + host =3D devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); > > + if (!host) > > + return -ENOMEM; > > + > > + /* Get the addresses */ > > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + base =3D devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(base)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(base), > > + "get resource failed.\n"); > > + > > + host->regmap =3D devm_regmap_init_mmio(&pdev->dev, base, > > + &sun50i_dmic_regmap_confi= g); > > Your second line should be aligned on the opening parenthesis > > > + /* Clocks */ > > + host->bus_clk =3D devm_clk_get(&pdev->dev, "bus"); > > + if (IS_ERR(host->bus_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk), > > + "failed to get bus clock.\n"); > > + > > + host->dmic_clk =3D devm_clk_get(&pdev->dev, "mod"); > > + if (IS_ERR(host->dmic_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk), > > + "failed to get dmic clock.\n"); > > + > > + host->dma_params_rx.addr =3D res->start + SUN50I_DMIC_DATA; > > + host->dma_params_rx.maxburst =3D 8; > > + > > + platform_set_drvdata(pdev, host); > > + > > + host->rst =3D devm_reset_control_get_optional_exclusive(&pdev->de= v, NULL); > > + if (IS_ERR(host->rst)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->rst), > > + "Failed to get reset.\n"); > > Your binding states that the reset is mandatory so you don't need the > optional variant. > > > + reset_control_deassert(host->rst); > > Can't this be moved to the runtime_pm hooks? Is this necessary? I see that most of the driver files execute reset_control_deassert in the probe function, and reset_control_assert in the remove function. > > > + ret =3D devm_snd_soc_register_component(&pdev->dev, > > + &sun50i_dmic_component, &sun50i_dmic_dai,= 1); > > Your second line should be aligned on the opening parenthesis > > > + if (ret) > > + return dev_err_probe(&pdev->dev, ret, > > + "failed to register component.\n"); > > + > > + pm_runtime_enable(&pdev->dev); > > + if (!pm_runtime_enabled(&pdev->dev)) { > > + ret =3D sun50i_dmic_runtime_resume(&pdev->dev); > > + if (ret) > > + goto err_unregister; > > + } > > We have a depends on PM on some drivers already, so I guess it would > just make sense to add one more here instead of dealing with whether > runtime_pm is compiled in or not. I don't understand. I am referring to the sun4i-spdif.c file. Which driver files should I refer to? > > Also, the name of the label is misleading: it's called err_unregister > but you don't need to unregister anything and you actually disable > runtime_pm for that device. > > err_disable_runtime_pm or something similar would be a better pick > > Thanks! > Maxime From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2173C4338F for ; Sun, 1 Aug 2021 09:48:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AE9D4610A6 for ; Sun, 1 Aug 2021 09:48:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231672AbhHAJsG (ORCPT ); Sun, 1 Aug 2021 05:48:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231464AbhHAJsF (ORCPT ); Sun, 1 Aug 2021 05:48:05 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 61925C06175F for ; Sun, 1 Aug 2021 02:47:57 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id dw2-20020a17090b0942b0290177cb475142so1439741pjb.2 for ; Sun, 01 Aug 2021 02:47:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=L4zxM4cwYaEtb0LsuZc0Nq6yIU8PNzb7rVpdAyyjN3Qz09GTkRmqaJG7oKR4dxaWU6 hlwNuK8q11HeOlO7HMBlY7wOrB3Nsh15pIBdar7tyI7bF8asV+tbIq9Jj33r47HuyhRH IOOwlZNlaCV0D10goupNP4TADB/zlHqgo38lYguc64Ns7kaITpqaPlCxHdek9MdIH70v xjFAmQlprOBa4hvfclEmvN2iAWEAjA2VpvQqe6wo/pOFmImHCW1BKJiHUqTYiUbJYlKj 37b5KDgLrWHkk+jYHoKleLNbHCvfF9hcTjZzksPJteti//b61nH8uCC94nx6Le3kwgrL nBoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=a6aqp4XgAXkBZUQo/iXmjG+nxln08O27+m8fGzTUxxTZR9AoXSWiMa9oJCgc/3GMUq gWrLCWB5IKOlitdCqZRTmUnvjc45kCYAVI1FRGqA3h596aGVZFcd5jIABcieoCoDmx+S f3bKNniSOOXRAQlWgXEbr3Eh8sRTRObgdPcBR0qTPdM0dNPG34FFZ+QhhmGWZvHrIfy1 mvxdWCzsy9liWteIhsK2YZ0OmK4k7FsBlWIMwBDjXum/jLlk4x7D39KVsowf6TIuGl2S rgwMhOJKtiA4E78uoWe9mRs2YBvaeB7bho4t0Dtrt0fhdYb+ReYzzmM8fgqNDvSpZHmU d9lA== X-Gm-Message-State: AOAM5317DMMl58XhoO9+wYWXhAPifUwuivzr9aNdqzf8vLxczqZhaZ5C 1CD2BU+aCZyLCNDtR1YL5tEdpr1OtVoiaHDHIg== X-Google-Smtp-Source: ABdhPJw+tr2GBOalJTQGoLDnu3vIb3xXi8UtX9Wb7GNDzZbodvVLRBmN/5cJrIfzRPYkc98i2oWEtJMoD7pd10Yhytk= X-Received: by 2002:a62:4e0f:0:b029:329:20be:287a with SMTP id c15-20020a624e0f0000b029032920be287amr11522272pfb.55.1627811276782; Sun, 01 Aug 2021 02:47:56 -0700 (PDT) MIME-Version: 1.0 References: <20210711122055.4529-1-fengzheng923@gmail.com> <20210715074750.ewbggulc5kast6ez@gilmour> In-Reply-To: <20210715074750.ewbggulc5kast6ez@gilmour> From: =?UTF-8?B?54+t5rab?= Date: Sun, 1 Aug 2021 17:47:46 +0800 Message-ID: Subject: Re: [PATCH v6 1/2] ASoC: sunxi: Add Allwinner H6 Digital MIC driver To: Maxime Ripard Cc: lgirdwood@gmail.com, Mark Brown , perex@perex.cz, tiwai@suse.com, wens@csie.org, jernej.skrabec@gmail.com, p.zabel@pengutronix.de, Samuel Holland , krzk@kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, Dear: Maxime Ripard =E4=BA=8E2021=E5=B9=B47=E6=9C=8815=E6=97= =A5=E5=91=A8=E5=9B=9B =E4=B8=8B=E5=8D=883:47=E5=86=99=E9=81=93=EF=BC=9A > > Hi > > On Sun, Jul 11, 2021 at 08:20:55AM -0400, fengzheng923@gmail.com wrote: > > From: Ban Tao > > > > The Allwinner H6 and later SoCs have an DMIC block > > which is capable of capture. > > > > Signed-off-by: Ban Tao > > > > --- > > v1->v2: > > 1.Fix some compilation errors. > > 2.Modify some code styles. > > --- > > v2->v3: > > None. > > --- > > v3->v4: > > 1.add sig_bits. > > --- > > v4->v5: > > None. > > --- > > v5->v6: > > 1.Modify RXFIFO_CTL_MODE to mode 1. > > --- > > MAINTAINERS | 7 + > > sound/soc/sunxi/Kconfig | 8 + > > sound/soc/sunxi/Makefile | 1 + > > sound/soc/sunxi/sun50i-dmic.c | 403 ++++++++++++++++++++++++++++++++++ > > 4 files changed, 419 insertions(+) > > create mode 100644 sound/soc/sunxi/sun50i-dmic.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index e924f9e5df97..8d700baaa3ca 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -760,6 +760,13 @@ L: linux-media@vger.kernel.org > > S: Maintained > > F: drivers/staging/media/sunxi/cedrus/ > > > > +ALLWINNER DMIC DRIVERS > > +M: Ban Tao > > +L: alsa-devel@alsa-project.org (moderated for non-subscribers) > > +S: Maintained > > +F: Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.= yaml > > +F: sound/soc/sunxi/sun50i-dmic.c > > + > > ALPHA PORT > > M: Richard Henderson > > M: Ivan Kokshaysky > > diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig > > index ddcaaa98d3cb..2a3bf7722e11 100644 > > --- a/sound/soc/sunxi/Kconfig > > +++ b/sound/soc/sunxi/Kconfig > > @@ -56,6 +56,14 @@ config SND_SUN4I_SPDIF > > Say Y or M to add support for the S/PDIF audio block in the All= winner > > A10 and affiliated SoCs. > > > > +config SND_SUN50I_DMIC > > + tristate "Allwinner H6 DMIC Support" > > + depends on (OF && ARCH_SUNXI) || COMPILE_TEST > > + select SND_SOC_GENERIC_DMAENGINE_PCM > > + help > > + Say Y or M to add support for the DMIC audio block in the Allwi= nner > > + H6 and affiliated SoCs. > > + > > config SND_SUN8I_ADDA_PR_REGMAP > > tristate > > select REGMAP > > diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile > > index a86be340a076..4483fe9c94ef 100644 > > --- a/sound/soc/sunxi/Makefile > > +++ b/sound/soc/sunxi/Makefile > > @@ -6,3 +6,4 @@ obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) +=3D sun8i-codec-a= nalog.o > > obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) +=3D sun50i-codec-analog.o > > obj-$(CONFIG_SND_SUN8I_CODEC) +=3D sun8i-codec.o > > obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) +=3D sun8i-adda-pr-regmap.o > > +obj-$(CONFIG_SND_SUN50I_DMIC) +=3D sun50i-dmic.o > > diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmi= c.c > > new file mode 100644 > > index 000000000000..bbac836ba4de > > --- /dev/null > > +++ b/sound/soc/sunxi/sun50i-dmic.c > > @@ -0,0 +1,403 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +// > > +// This driver supports the DMIC in Allwinner's H6 SoCs. > > +// > > +// Copyright 2021 Ban Tao > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define SUN50I_DMIC_EN_CTL (0x00) > > + #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8) > > + #define SUN50I_DMIC_EN_CTL_CHAN(v) ((v) << 0) > > + #define SUN50I_DMIC_EN_CTL_CHAN_MASK GENMASK(7, 0) > > +#define SUN50I_DMIC_SR (0x04) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE(v) ((v) << 0) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CTL (0x08) > > + #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE BIT(0) > > +#define SUN50I_DMIC_DATA (0x10) > > +#define SUN50I_DMIC_INTC (0x14) > > + #define SUN50I_DMIC_FIFO_DRQ_EN BIT(2) > > +#define SUN50I_DMIC_INT_STA (0x18) > > + #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING BIT(1) > > + #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING BIT(0) > > +#define SUN50I_DMIC_RXFIFO_CTL (0x1c) > > + #define SUN50I_DMIC_RXFIFO_CTL_FLUSH BIT(31) > > + #define SUN50I_DMIC_RXFIFO_CTL_MODE BIT(9) > > + #define SUN50I_DMIC_RXFIFO_CTL_RESOLUTION BIT(8) > > +#define SUN50I_DMIC_CH_NUM (0x24) > > + #define SUN50I_DMIC_CH_NUM_N(v) ((v) << 0) > > + #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CNT (0x2c) > > + #define SUN50I_DMIC_CNT_N BIT(0) > > +#define SUN50I_DMIC_HPF_CTRL (0x38) > > +#define SUN50I_DMIC_VERSION (0x50) > > + > > + > > There's multiple blank lines here > > > +struct sun50i_dmic_dev { > > + struct clk *dmic_clk; > > + struct clk *bus_clk; > > + struct reset_control *rst; > > + struct regmap *regmap; > > + struct snd_dmaengine_dai_dma_data dma_params_rx; > > + unsigned int chan_en; > > +}; > > + > > +struct dmic_rate { > > + unsigned int samplerate; > > + unsigned int rate_bit; > > +}; > > + > > +static int sun50i_dmic_startup(struct snd_pcm_substream *substream, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + struct snd_soc_pcm_runtime *rtd =3D substream->private_data; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(asoc_rtd= _to_cpu(rtd, 0)); > > + > > + /* only support capture */ > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH); > > + regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream, > > + struct snd_pcm_hw_params *params, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + int i =3D 0; > > + unsigned long rate =3D params_rate(params); > > + unsigned int mclk =3D 0; > > + unsigned int channels =3D params_channels(params); > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(cpu_dai)= ; > > + static struct dmic_rate dmic_rate_s[] =3D { > > + {44100, 0x0}, > > + {48000, 0x0}, > > + {22050, 0x2}, > > + {24000, 0x2}, > > + {11025, 0x4}, > > + {12000, 0x4}, > > + {32000, 0x1}, > > + {16000, 0x3}, > > + {8000, 0x5}, > > + }; > > We should order these items. It looks like descending rate makes the > most sense? > > Also, I'm not sure why we need to make that array local, can't this be a > global variable? > > > + /* DMIC num is N+1 */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM, > > + SUN50I_DMIC_CH_NUM_N_MASK, > > + SUN50I_DMIC_CH_NUM_N(channels - 1)); > > + host->chan_en =3D (1 << channels) - 1; > > + regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, host->chan_en); > > Do we need to store the channels bitmask in the main structure? It looks > fairly easy to generate, so I guess we could just use a macro I need to store channels bitmask and use it in sun50i_dmic_trigger function= . > > > + switch (params_format(params)) { > > + case SNDRV_PCM_FORMAT_S16_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, 0); > > + break; > > + case SNDRV_PCM_FORMAT_S24_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION); > > + break; > > These two defines could be named a bit better, it's not really clear > what SUN50I_DMIC_RXFIFO_CTL_RESOLUTION means, exactly, as opposed to 0 > (while it's actually the sample width). > > What about something like SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16 (for 0) and > _24 (for 1), while changing SUN50I_DMIC_RXFIFO_CTL_RESOLUTION for > SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK ? > > > + default: > > + dev_err(cpu_dai->dev, "Invalid format!\n"); > > + return -EINVAL; > > + } > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_MODE, > > + SUN50I_DMIC_RXFIFO_CTL_MODE); > > Same thing here, MODE doesn't really explain what this does, and why > we'd want to always set it. > > I guess 0 is LSB_ZERO and 1 is MSB_SIGN? Yes. > > > + switch (rate) { > > + case 11025: > > + case 22050: > > + case 44100: > > + mclk =3D 22579200; > > + break; > > + case 8000: > > + case 12000: > > + case 16000: > > + case 24000: > > + case 32000: > > + case 48000: > > + mclk =3D 24576000; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Invalid rate!\n"); > > + return -EINVAL; > > + } > > + > > + if (clk_set_rate(host->dmic_clk, mclk)) { > > + dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk); > > + return -EINVAL; > > + } > > + > > + for (i =3D 0; i < ARRAY_SIZE(dmic_rate_s); i++) { > > + if (dmic_rate_s[i].samplerate =3D=3D rate) { > > + regmap_update_bits(host->regmap, SUN50I_DMIC_SR, > > + SUN50I_DMIC_SR_SAMPLE_RATE_MAS= K, > > + SUN50I_DMIC_SR_SAMPLE_RATE(dmi= c_rate_s[i].rate_bit)); > > + break; > > + } > > + } > > + > > + switch (params_physical_width(params)) { > > + case 16: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_2_B= YTES; > > + break; > > + case 32: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_4_B= YTES; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Unsupported physical sample width:= %d\n", > > + params_physical_width(params)); > > + return -EINVAL; > > + } > > + > > + /* oversamplerate adjust */ > > + if (params_rate(params) >=3D 24000) > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE); > > + else > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, in= t cmd, > > + struct snd_soc_dai *dai) > > +{ > > + int ret =3D 0; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + switch (cmd) { > > + case SNDRV_PCM_TRIGGER_START: > > + case SNDRV_PCM_TRIGGER_RESUME: > > + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > > + /* DRQ ENABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, > > + SUN50I_DMIC_FIFO_DRQ_EN); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(host->chan_en)= ); > > + /* Global enable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, > > + SUN50I_DMIC_EN_CTL_GLOBE); > > + break; > > Do we really need to clear the channel and global enable bits? and DRQ? Why not? I think we should clear them when not in use...... > > > + case SNDRV_PCM_TRIGGER_STOP: > > + case SNDRV_PCM_TRIGGER_SUSPEND: > > + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: > > + /* DRQ DISABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, 0); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(0)); > > + /* Global disable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, 0); > > + break; > > + > > + default: > > + ret =3D -EINVAL; > > + break; > > + } > > + return ret; > > +} > > + > > +static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai) > > +{ > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx); > > + > > + return 0; > > +} > > + > > +static const struct snd_soc_dai_ops sun50i_dmic_dai_ops =3D { > > + .startup =3D sun50i_dmic_startup, > > + .trigger =3D sun50i_dmic_trigger, > > + .hw_params =3D sun50i_dmic_hw_params, > > +}; > > + > > +static const struct regmap_config sun50i_dmic_regmap_config =3D { > > + .reg_bits =3D 32, > > + .reg_stride =3D 4, > > + .val_bits =3D 32, > > + .max_register =3D SUN50I_DMIC_VERSION, > > + .cache_type =3D REGCACHE_NONE, > > +}; > > + > > +#define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000) > > +#define SUN50I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTB= IT_S24_LE) > > SUN50I_DMIC_RATES has a tab between the define and its name, while > SUN50I_FORMATS has the tab after the name. We should be consistent. > Similarly, we should name both with the SUN50I_DMIC prefix. > > > +static struct snd_soc_dai_driver sun50i_dmic_dai =3D { > > + .capture =3D { > > + .channels_min =3D 1, > > + .channels_max =3D 8, > > + .rates =3D SUN50I_DMIC_RATES, > > + .formats =3D SUN50I_FORMATS, > > + .sig_bits =3D 21, > > + }, > > + .probe =3D sun50i_dmic_soc_dai_probe, > > + .ops =3D &sun50i_dmic_dai_ops, > > + .name =3D "dmic", > > +}; > > + > > +static const struct of_device_id sun50i_dmic_of_match[] =3D { > > + { > > + .compatible =3D "allwinner,sun50i-h6-dmic", > > + }, > > + { /* sentinel */ } > > +}; > > +MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match); > > + > > +static const struct snd_soc_component_driver sun50i_dmic_component =3D= { > > + .name =3D "sun50i-dmic", > > +}; > > + > > +static int sun50i_dmic_runtime_suspend(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + > > + clk_disable_unprepare(host->dmic_clk); > > + clk_disable_unprepare(host->bus_clk); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_runtime_resume(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + int ret; > > + > > + ret =3D clk_prepare_enable(host->dmic_clk); > > + if (ret) > > + return ret; > > A new line here would be great. > > > + ret =3D clk_prepare_enable(host->bus_clk); > > + if (ret) > > + clk_disable_unprepare(host->dmic_clk); > > + > > + return ret; > > In general we prefer to treat the error path and the success path > differently. In this case it would mean changing that part to > > ret =3D clk_prepare_enable(host->bus_clk); > if (ret) { > clk_disable_unprepare(host->dmic_clk); > return ret; > } > > return 0; > > > +} > > + > > +static int sun50i_dmic_probe(struct platform_device *pdev) > > +{ > > + struct sun50i_dmic_dev *host; > > + struct resource *res; > > + int ret; > > + void __iomem *base; > > + > > + host =3D devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); > > + if (!host) > > + return -ENOMEM; > > + > > + /* Get the addresses */ > > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + base =3D devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(base)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(base), > > + "get resource failed.\n"); > > + > > + host->regmap =3D devm_regmap_init_mmio(&pdev->dev, base, > > + &sun50i_dmic_regmap_confi= g); > > Your second line should be aligned on the opening parenthesis > > > + /* Clocks */ > > + host->bus_clk =3D devm_clk_get(&pdev->dev, "bus"); > > + if (IS_ERR(host->bus_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk), > > + "failed to get bus clock.\n"); > > + > > + host->dmic_clk =3D devm_clk_get(&pdev->dev, "mod"); > > + if (IS_ERR(host->dmic_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk), > > + "failed to get dmic clock.\n"); > > + > > + host->dma_params_rx.addr =3D res->start + SUN50I_DMIC_DATA; > > + host->dma_params_rx.maxburst =3D 8; > > + > > + platform_set_drvdata(pdev, host); > > + > > + host->rst =3D devm_reset_control_get_optional_exclusive(&pdev->de= v, NULL); > > + if (IS_ERR(host->rst)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->rst), > > + "Failed to get reset.\n"); > > Your binding states that the reset is mandatory so you don't need the > optional variant. > > > + reset_control_deassert(host->rst); > > Can't this be moved to the runtime_pm hooks? Is this necessary? I see that most of the driver files execute reset_control_deassert in the probe function, and reset_control_assert in the remove function. > > > + ret =3D devm_snd_soc_register_component(&pdev->dev, > > + &sun50i_dmic_component, &sun50i_dmic_dai,= 1); > > Your second line should be aligned on the opening parenthesis > > > + if (ret) > > + return dev_err_probe(&pdev->dev, ret, > > + "failed to register component.\n"); > > + > > + pm_runtime_enable(&pdev->dev); > > + if (!pm_runtime_enabled(&pdev->dev)) { > > + ret =3D sun50i_dmic_runtime_resume(&pdev->dev); > > + if (ret) > > + goto err_unregister; > > + } > > We have a depends on PM on some drivers already, so I guess it would > just make sense to add one more here instead of dealing with whether > runtime_pm is compiled in or not. I don't understand. I am referring to the sun4i-spdif.c file. Which driver files should I refer to? > > Also, the name of the label is misleading: it's called err_unregister > but you don't need to unregister anything and you actually disable > runtime_pm for that device. > > err_disable_runtime_pm or something similar would be a better pick > > Thanks! > Maxime From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76607C4338F for ; Sun, 1 Aug 2021 09:49:01 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D35E610A1 for ; Sun, 1 Aug 2021 09:48:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1D35E610A1 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id C60C71872; Sun, 1 Aug 2021 11:48:07 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C60C71872 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1627811337; bh=dle4XILej63KXMoLEHebTKjf6atXs3yQYDfA7GD/1Kc=; h=References:In-Reply-To:From:Date:Subject:To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Pu9qw573tlMmR9z0yIDmbINCAT7nEP2USoHBmCitI3b5wsE9Tnz7uHZgXqHPN1j7f Mvvg+wzMzBomnU7fGG7baSWR0ZYSoPO3ppovxkjled4EAVNaj2c1JXymXx1e09I1eK +b7XDLMWeKpFPGWVRX+zdCjmbFAgHu56v6eeCPcQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 2B18AF8016D; Sun, 1 Aug 2021 11:48:07 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id ED4A8F802E8; Sun, 1 Aug 2021 11:48:05 +0200 (CEST) Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7518AF8014D for ; Sun, 1 Aug 2021 11:47:58 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7518AF8014D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="L4zxM4cw" Received: by mail-pj1-x1031.google.com with SMTP id mz5-20020a17090b3785b0290176ecf64922so27292887pjb.3 for ; Sun, 01 Aug 2021 02:47:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=L4zxM4cwYaEtb0LsuZc0Nq6yIU8PNzb7rVpdAyyjN3Qz09GTkRmqaJG7oKR4dxaWU6 hlwNuK8q11HeOlO7HMBlY7wOrB3Nsh15pIBdar7tyI7bF8asV+tbIq9Jj33r47HuyhRH IOOwlZNlaCV0D10goupNP4TADB/zlHqgo38lYguc64Ns7kaITpqaPlCxHdek9MdIH70v xjFAmQlprOBa4hvfclEmvN2iAWEAjA2VpvQqe6wo/pOFmImHCW1BKJiHUqTYiUbJYlKj 37b5KDgLrWHkk+jYHoKleLNbHCvfF9hcTjZzksPJteti//b61nH8uCC94nx6Le3kwgrL nBoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=Vc4GRgv0wL9VFih+64Psdaxvfi0QYOipGhx80SE8j9Y51supXuhULg9hGRdxrF9+8p Jfc8sZUYg9yBuNs3RylGmSwhM2ZAGAoECs2r/LXAL3icVABr6iiiZ1PFD2g2Ud5O4sYi w4YI0PrvOQAFaBjfHevTtpMbBMMvNXBoVIBAAsGoxDDjgQ/fQHR6Rh0fVT0XmmlFtBsO 3Vux6yH9DKXHxGMt7u+ppbdcJZSMN/k9i7AyheKLmu1pautQ0lQ6870aqWwv6tJ3s99v BZLnrx4/NoDN3tGseRYDAz9SoPm8U/+8MUnCORG8J7owpQ8Rxb9Rzw77vLsTugG3JiW2 QcqQ== X-Gm-Message-State: AOAM532m2RFJfuY9oSks7muTUEXyxAfSmlPP1cAv5m9I9ZcMp4nfweRN uEsijB5i6nwV/nZmAQNeo7zClRo3Er7cii1NfQ== X-Google-Smtp-Source: ABdhPJw+tr2GBOalJTQGoLDnu3vIb3xXi8UtX9Wb7GNDzZbodvVLRBmN/5cJrIfzRPYkc98i2oWEtJMoD7pd10Yhytk= X-Received: by 2002:a62:4e0f:0:b029:329:20be:287a with SMTP id c15-20020a624e0f0000b029032920be287amr11522272pfb.55.1627811276782; Sun, 01 Aug 2021 02:47:56 -0700 (PDT) MIME-Version: 1.0 References: <20210711122055.4529-1-fengzheng923@gmail.com> <20210715074750.ewbggulc5kast6ez@gilmour> In-Reply-To: <20210715074750.ewbggulc5kast6ez@gilmour> From: =?UTF-8?B?54+t5rab?= Date: Sun, 1 Aug 2021 17:47:46 +0800 Message-ID: Subject: Re: [PATCH v6 1/2] ASoC: sunxi: Add Allwinner H6 Digital MIC driver To: Maxime Ripard Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Cc: alsa-devel@alsa-project.org, Samuel Holland , linux-kernel@vger.kernel.org, tiwai@suse.com, jernej.skrabec@gmail.com, lgirdwood@gmail.com, wens@csie.org, Mark Brown , krzk@kernel.org, p.zabel@pengutronix.de, linux-sunxi@lists.linux.dev, linux-arm-kernel@lists.infradead.org X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Hi, Dear: Maxime Ripard =E4=BA=8E2021=E5=B9=B47=E6=9C=8815=E6=97= =A5=E5=91=A8=E5=9B=9B =E4=B8=8B=E5=8D=883:47=E5=86=99=E9=81=93=EF=BC=9A > > Hi > > On Sun, Jul 11, 2021 at 08:20:55AM -0400, fengzheng923@gmail.com wrote: > > From: Ban Tao > > > > The Allwinner H6 and later SoCs have an DMIC block > > which is capable of capture. > > > > Signed-off-by: Ban Tao > > > > --- > > v1->v2: > > 1.Fix some compilation errors. > > 2.Modify some code styles. > > --- > > v2->v3: > > None. > > --- > > v3->v4: > > 1.add sig_bits. > > --- > > v4->v5: > > None. > > --- > > v5->v6: > > 1.Modify RXFIFO_CTL_MODE to mode 1. > > --- > > MAINTAINERS | 7 + > > sound/soc/sunxi/Kconfig | 8 + > > sound/soc/sunxi/Makefile | 1 + > > sound/soc/sunxi/sun50i-dmic.c | 403 ++++++++++++++++++++++++++++++++++ > > 4 files changed, 419 insertions(+) > > create mode 100644 sound/soc/sunxi/sun50i-dmic.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index e924f9e5df97..8d700baaa3ca 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -760,6 +760,13 @@ L: linux-media@vger.kernel.org > > S: Maintained > > F: drivers/staging/media/sunxi/cedrus/ > > > > +ALLWINNER DMIC DRIVERS > > +M: Ban Tao > > +L: alsa-devel@alsa-project.org (moderated for non-subscribers) > > +S: Maintained > > +F: Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.= yaml > > +F: sound/soc/sunxi/sun50i-dmic.c > > + > > ALPHA PORT > > M: Richard Henderson > > M: Ivan Kokshaysky > > diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig > > index ddcaaa98d3cb..2a3bf7722e11 100644 > > --- a/sound/soc/sunxi/Kconfig > > +++ b/sound/soc/sunxi/Kconfig > > @@ -56,6 +56,14 @@ config SND_SUN4I_SPDIF > > Say Y or M to add support for the S/PDIF audio block in the All= winner > > A10 and affiliated SoCs. > > > > +config SND_SUN50I_DMIC > > + tristate "Allwinner H6 DMIC Support" > > + depends on (OF && ARCH_SUNXI) || COMPILE_TEST > > + select SND_SOC_GENERIC_DMAENGINE_PCM > > + help > > + Say Y or M to add support for the DMIC audio block in the Allwi= nner > > + H6 and affiliated SoCs. > > + > > config SND_SUN8I_ADDA_PR_REGMAP > > tristate > > select REGMAP > > diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile > > index a86be340a076..4483fe9c94ef 100644 > > --- a/sound/soc/sunxi/Makefile > > +++ b/sound/soc/sunxi/Makefile > > @@ -6,3 +6,4 @@ obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) +=3D sun8i-codec-a= nalog.o > > obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) +=3D sun50i-codec-analog.o > > obj-$(CONFIG_SND_SUN8I_CODEC) +=3D sun8i-codec.o > > obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) +=3D sun8i-adda-pr-regmap.o > > +obj-$(CONFIG_SND_SUN50I_DMIC) +=3D sun50i-dmic.o > > diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmi= c.c > > new file mode 100644 > > index 000000000000..bbac836ba4de > > --- /dev/null > > +++ b/sound/soc/sunxi/sun50i-dmic.c > > @@ -0,0 +1,403 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +// > > +// This driver supports the DMIC in Allwinner's H6 SoCs. > > +// > > +// Copyright 2021 Ban Tao > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define SUN50I_DMIC_EN_CTL (0x00) > > + #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8) > > + #define SUN50I_DMIC_EN_CTL_CHAN(v) ((v) << 0) > > + #define SUN50I_DMIC_EN_CTL_CHAN_MASK GENMASK(7, 0) > > +#define SUN50I_DMIC_SR (0x04) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE(v) ((v) << 0) > > + #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CTL (0x08) > > + #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE BIT(0) > > +#define SUN50I_DMIC_DATA (0x10) > > +#define SUN50I_DMIC_INTC (0x14) > > + #define SUN50I_DMIC_FIFO_DRQ_EN BIT(2) > > +#define SUN50I_DMIC_INT_STA (0x18) > > + #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING BIT(1) > > + #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING BIT(0) > > +#define SUN50I_DMIC_RXFIFO_CTL (0x1c) > > + #define SUN50I_DMIC_RXFIFO_CTL_FLUSH BIT(31) > > + #define SUN50I_DMIC_RXFIFO_CTL_MODE BIT(9) > > + #define SUN50I_DMIC_RXFIFO_CTL_RESOLUTION BIT(8) > > +#define SUN50I_DMIC_CH_NUM (0x24) > > + #define SUN50I_DMIC_CH_NUM_N(v) ((v) << 0) > > + #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0) > > +#define SUN50I_DMIC_CNT (0x2c) > > + #define SUN50I_DMIC_CNT_N BIT(0) > > +#define SUN50I_DMIC_HPF_CTRL (0x38) > > +#define SUN50I_DMIC_VERSION (0x50) > > + > > + > > There's multiple blank lines here > > > +struct sun50i_dmic_dev { > > + struct clk *dmic_clk; > > + struct clk *bus_clk; > > + struct reset_control *rst; > > + struct regmap *regmap; > > + struct snd_dmaengine_dai_dma_data dma_params_rx; > > + unsigned int chan_en; > > +}; > > + > > +struct dmic_rate { > > + unsigned int samplerate; > > + unsigned int rate_bit; > > +}; > > + > > +static int sun50i_dmic_startup(struct snd_pcm_substream *substream, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + struct snd_soc_pcm_runtime *rtd =3D substream->private_data; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(asoc_rtd= _to_cpu(rtd, 0)); > > + > > + /* only support capture */ > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH, > > + SUN50I_DMIC_RXFIFO_CTL_FLUSH); > > + regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream, > > + struct snd_pcm_hw_params *params, > > + struct snd_soc_dai *cpu_dai) > > +{ > > + int i =3D 0; > > + unsigned long rate =3D params_rate(params); > > + unsigned int mclk =3D 0; > > + unsigned int channels =3D params_channels(params); > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(cpu_dai)= ; > > + static struct dmic_rate dmic_rate_s[] =3D { > > + {44100, 0x0}, > > + {48000, 0x0}, > > + {22050, 0x2}, > > + {24000, 0x2}, > > + {11025, 0x4}, > > + {12000, 0x4}, > > + {32000, 0x1}, > > + {16000, 0x3}, > > + {8000, 0x5}, > > + }; > > We should order these items. It looks like descending rate makes the > most sense? > > Also, I'm not sure why we need to make that array local, can't this be a > global variable? > > > + /* DMIC num is N+1 */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM, > > + SUN50I_DMIC_CH_NUM_N_MASK, > > + SUN50I_DMIC_CH_NUM_N(channels - 1)); > > + host->chan_en =3D (1 << channels) - 1; > > + regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, host->chan_en); > > Do we need to store the channels bitmask in the main structure? It looks > fairly easy to generate, so I guess we could just use a macro I need to store channels bitmask and use it in sun50i_dmic_trigger function= . > > > + switch (params_format(params)) { > > + case SNDRV_PCM_FORMAT_S16_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, 0); > > + break; > > + case SNDRV_PCM_FORMAT_S24_LE: > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION, > > + SUN50I_DMIC_RXFIFO_CTL_RESOLUTION); > > + break; > > These two defines could be named a bit better, it's not really clear > what SUN50I_DMIC_RXFIFO_CTL_RESOLUTION means, exactly, as opposed to 0 > (while it's actually the sample width). > > What about something like SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16 (for 0) and > _24 (for 1), while changing SUN50I_DMIC_RXFIFO_CTL_RESOLUTION for > SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK ? > > > + default: > > + dev_err(cpu_dai->dev, "Invalid format!\n"); > > + return -EINVAL; > > + } > > + regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, > > + SUN50I_DMIC_RXFIFO_CTL_MODE, > > + SUN50I_DMIC_RXFIFO_CTL_MODE); > > Same thing here, MODE doesn't really explain what this does, and why > we'd want to always set it. > > I guess 0 is LSB_ZERO and 1 is MSB_SIGN? Yes. > > > + switch (rate) { > > + case 11025: > > + case 22050: > > + case 44100: > > + mclk =3D 22579200; > > + break; > > + case 8000: > > + case 12000: > > + case 16000: > > + case 24000: > > + case 32000: > > + case 48000: > > + mclk =3D 24576000; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Invalid rate!\n"); > > + return -EINVAL; > > + } > > + > > + if (clk_set_rate(host->dmic_clk, mclk)) { > > + dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk); > > + return -EINVAL; > > + } > > + > > + for (i =3D 0; i < ARRAY_SIZE(dmic_rate_s); i++) { > > + if (dmic_rate_s[i].samplerate =3D=3D rate) { > > + regmap_update_bits(host->regmap, SUN50I_DMIC_SR, > > + SUN50I_DMIC_SR_SAMPLE_RATE_MAS= K, > > + SUN50I_DMIC_SR_SAMPLE_RATE(dmi= c_rate_s[i].rate_bit)); > > + break; > > + } > > + } > > + > > + switch (params_physical_width(params)) { > > + case 16: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_2_B= YTES; > > + break; > > + case 32: > > + host->dma_params_rx.addr_width =3D DMA_SLAVE_BUSWIDTH_4_B= YTES; > > + break; > > + default: > > + dev_err(cpu_dai->dev, "Unsupported physical sample width:= %d\n", > > + params_physical_width(params)); > > + return -EINVAL; > > + } > > + > > + /* oversamplerate adjust */ > > + if (params_rate(params) >=3D 24000) > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE); > > + else > > + regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, > > + SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, in= t cmd, > > + struct snd_soc_dai *dai) > > +{ > > + int ret =3D 0; > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + if (substream->stream !=3D SNDRV_PCM_STREAM_CAPTURE) > > + return -EINVAL; > > + > > + switch (cmd) { > > + case SNDRV_PCM_TRIGGER_START: > > + case SNDRV_PCM_TRIGGER_RESUME: > > + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > > + /* DRQ ENABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, > > + SUN50I_DMIC_FIFO_DRQ_EN); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(host->chan_en)= ); > > + /* Global enable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, > > + SUN50I_DMIC_EN_CTL_GLOBE); > > + break; > > Do we really need to clear the channel and global enable bits? and DRQ? Why not? I think we should clear them when not in use...... > > > + case SNDRV_PCM_TRIGGER_STOP: > > + case SNDRV_PCM_TRIGGER_SUSPEND: > > + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: > > + /* DRQ DISABLE */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, > > + SUN50I_DMIC_FIFO_DRQ_EN, 0); > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_CHAN_MASK, > > + SUN50I_DMIC_EN_CTL_CHAN(0)); > > + /* Global disable */ > > + regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, > > + SUN50I_DMIC_EN_CTL_GLOBE, 0); > > + break; > > + > > + default: > > + ret =3D -EINVAL; > > + break; > > + } > > + return ret; > > +} > > + > > +static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai) > > +{ > > + struct sun50i_dmic_dev *host =3D snd_soc_dai_get_drvdata(dai); > > + > > + snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx); > > + > > + return 0; > > +} > > + > > +static const struct snd_soc_dai_ops sun50i_dmic_dai_ops =3D { > > + .startup =3D sun50i_dmic_startup, > > + .trigger =3D sun50i_dmic_trigger, > > + .hw_params =3D sun50i_dmic_hw_params, > > +}; > > + > > +static const struct regmap_config sun50i_dmic_regmap_config =3D { > > + .reg_bits =3D 32, > > + .reg_stride =3D 4, > > + .val_bits =3D 32, > > + .max_register =3D SUN50I_DMIC_VERSION, > > + .cache_type =3D REGCACHE_NONE, > > +}; > > + > > +#define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000) > > +#define SUN50I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTB= IT_S24_LE) > > SUN50I_DMIC_RATES has a tab between the define and its name, while > SUN50I_FORMATS has the tab after the name. We should be consistent. > Similarly, we should name both with the SUN50I_DMIC prefix. > > > +static struct snd_soc_dai_driver sun50i_dmic_dai =3D { > > + .capture =3D { > > + .channels_min =3D 1, > > + .channels_max =3D 8, > > + .rates =3D SUN50I_DMIC_RATES, > > + .formats =3D SUN50I_FORMATS, > > + .sig_bits =3D 21, > > + }, > > + .probe =3D sun50i_dmic_soc_dai_probe, > > + .ops =3D &sun50i_dmic_dai_ops, > > + .name =3D "dmic", > > +}; > > + > > +static const struct of_device_id sun50i_dmic_of_match[] =3D { > > + { > > + .compatible =3D "allwinner,sun50i-h6-dmic", > > + }, > > + { /* sentinel */ } > > +}; > > +MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match); > > + > > +static const struct snd_soc_component_driver sun50i_dmic_component =3D= { > > + .name =3D "sun50i-dmic", > > +}; > > + > > +static int sun50i_dmic_runtime_suspend(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + > > + clk_disable_unprepare(host->dmic_clk); > > + clk_disable_unprepare(host->bus_clk); > > + > > + return 0; > > +} > > + > > +static int sun50i_dmic_runtime_resume(struct device *dev) > > +{ > > + struct sun50i_dmic_dev *host =3D dev_get_drvdata(dev); > > + int ret; > > + > > + ret =3D clk_prepare_enable(host->dmic_clk); > > + if (ret) > > + return ret; > > A new line here would be great. > > > + ret =3D clk_prepare_enable(host->bus_clk); > > + if (ret) > > + clk_disable_unprepare(host->dmic_clk); > > + > > + return ret; > > In general we prefer to treat the error path and the success path > differently. In this case it would mean changing that part to > > ret =3D clk_prepare_enable(host->bus_clk); > if (ret) { > clk_disable_unprepare(host->dmic_clk); > return ret; > } > > return 0; > > > +} > > + > > +static int sun50i_dmic_probe(struct platform_device *pdev) > > +{ > > + struct sun50i_dmic_dev *host; > > + struct resource *res; > > + int ret; > > + void __iomem *base; > > + > > + host =3D devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); > > + if (!host) > > + return -ENOMEM; > > + > > + /* Get the addresses */ > > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + base =3D devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(base)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(base), > > + "get resource failed.\n"); > > + > > + host->regmap =3D devm_regmap_init_mmio(&pdev->dev, base, > > + &sun50i_dmic_regmap_confi= g); > > Your second line should be aligned on the opening parenthesis > > > + /* Clocks */ > > + host->bus_clk =3D devm_clk_get(&pdev->dev, "bus"); > > + if (IS_ERR(host->bus_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk), > > + "failed to get bus clock.\n"); > > + > > + host->dmic_clk =3D devm_clk_get(&pdev->dev, "mod"); > > + if (IS_ERR(host->dmic_clk)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk), > > + "failed to get dmic clock.\n"); > > + > > + host->dma_params_rx.addr =3D res->start + SUN50I_DMIC_DATA; > > + host->dma_params_rx.maxburst =3D 8; > > + > > + platform_set_drvdata(pdev, host); > > + > > + host->rst =3D devm_reset_control_get_optional_exclusive(&pdev->de= v, NULL); > > + if (IS_ERR(host->rst)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(host->rst), > > + "Failed to get reset.\n"); > > Your binding states that the reset is mandatory so you don't need the > optional variant. > > > + reset_control_deassert(host->rst); > > Can't this be moved to the runtime_pm hooks? Is this necessary? I see that most of the driver files execute reset_control_deassert in the probe function, and reset_control_assert in the remove function. > > > + ret =3D devm_snd_soc_register_component(&pdev->dev, > > + &sun50i_dmic_component, &sun50i_dmic_dai,= 1); > > Your second line should be aligned on the opening parenthesis > > > + if (ret) > > + return dev_err_probe(&pdev->dev, ret, > > + "failed to register component.\n"); > > + > > + pm_runtime_enable(&pdev->dev); > > + if (!pm_runtime_enabled(&pdev->dev)) { > > + ret =3D sun50i_dmic_runtime_resume(&pdev->dev); > > + if (ret) > > + goto err_unregister; > > + } > > We have a depends on PM on some drivers already, so I guess it would > just make sense to add one more here instead of dealing with whether > runtime_pm is compiled in or not. I don't understand. I am referring to the sun4i-spdif.c file. Which driver files should I refer to? > > Also, the name of the label is misleading: it's called err_unregister > but you don't need to unregister anything and you actually disable > runtime_pm for that device. > > err_disable_runtime_pm or something similar would be a better pick > > Thanks! > Maxime From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C312EC4338F for ; Sun, 1 Aug 2021 09:50:33 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8E0C7610A0 for ; Sun, 1 Aug 2021 09:50:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8E0C7610A0 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:Subject:Message-ID:Date:From: In-Reply-To:References:MIME-Version:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=5ISos8CHAR+Ap71om7VqD2AVSl9bw3hM3XRch9HwbRU=; b=DIlk1eEiZw1tVH yKsAvqhv2Y19K4SwGCePtmCIjxg/IgZ/cZMn61TDdO129htTMdefMY9LWAqQdyyYP0N32TtETlWmS ZDPGsCDH9XLsWi5y48kvfXALlrk+3ukvNESxXKOKv2WpRH3dT+qibOMBJFfuY6LXc+UJprBP+5snF CJ4/hqCuC4OyKsega+NIFdKD+DrQwIoDeP1MZ20YPlwnCf7v/0S1VD6FoI+6NRc4wyer52Dekwqu/ IMmGgWnMd4VmRKmySi3glBfNENILy9hLz57y2wy6hadm0PdSaoNfskkCQ34oNIAV/+eb315cHpyWZ OkYkHJgu9lex+g+MBgrA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mA84h-00D9fV-LJ; Sun, 01 Aug 2021 09:48:03 +0000 Received: from mail-pj1-x1036.google.com ([2607:f8b0:4864:20::1036]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mA84d-00D9ey-3z for linux-arm-kernel@lists.infradead.org; Sun, 01 Aug 2021 09:48:01 +0000 Received: by mail-pj1-x1036.google.com with SMTP id ds11-20020a17090b08cbb0290172f971883bso27352607pjb.1 for ; Sun, 01 Aug 2021 02:47:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=L4zxM4cwYaEtb0LsuZc0Nq6yIU8PNzb7rVpdAyyjN3Qz09GTkRmqaJG7oKR4dxaWU6 hlwNuK8q11HeOlO7HMBlY7wOrB3Nsh15pIBdar7tyI7bF8asV+tbIq9Jj33r47HuyhRH IOOwlZNlaCV0D10goupNP4TADB/zlHqgo38lYguc64Ns7kaITpqaPlCxHdek9MdIH70v xjFAmQlprOBa4hvfclEmvN2iAWEAjA2VpvQqe6wo/pOFmImHCW1BKJiHUqTYiUbJYlKj 37b5KDgLrWHkk+jYHoKleLNbHCvfF9hcTjZzksPJteti//b61nH8uCC94nx6Le3kwgrL nBoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=RHsoGJjgDOnzEi5IVMKsSdRnOK0IUJdpaPMyo84Tl68=; b=LuxLiTTOymSnc/h0KwtgvPsSJq44u2jLiQU0Ud3iEZDcCEG1p58Blf1JTNfJd8Be85 l/McD9omRg3rIxYLFLiTnShIoKeezOWNYWnXg+RxjRHbSZq97c1SbI1eLvtJC10wJmWB m1MMcl3mwD+pzNUnuyUTiycV72yq834Ed01kBPflpg+zsvzZElVUEgt2LdMPUj0kdQGt qcrQbcQJ+r9QEY/BjC5hoR4qU/YMtAtVgNucIV8n+igqVyzrxeI8nZYmFxo3KbnGtgqx Sk5X12HGsJXlAcvuEZXJd5+EM55KKVkQGeDD1g9paUuS8jSLaEmQ+lgkU5WDTd7Dlfxd IO4g== X-Gm-Message-State: AOAM533C8nZAQn3fXh4F472S7DDPct2dw0hBu6FQbdkOkkRvZbO917DU YhqIXYVY1upQPE6jsLq2zYSuL1e5mTuAkyS0Lg== X-Google-Smtp-Source: ABdhPJw+tr2GBOalJTQGoLDnu3vIb3xXi8UtX9Wb7GNDzZbodvVLRBmN/5cJrIfzRPYkc98i2oWEtJMoD7pd10Yhytk= X-Received: by 2002:a62:4e0f:0:b029:329:20be:287a with SMTP id c15-20020a624e0f0000b029032920be287amr11522272pfb.55.1627811276782; Sun, 01 Aug 2021 02:47:56 -0700 (PDT) MIME-Version: 1.0 References: <20210711122055.4529-1-fengzheng923@gmail.com> <20210715074750.ewbggulc5kast6ez@gilmour> In-Reply-To: <20210715074750.ewbggulc5kast6ez@gilmour> From: =?UTF-8?B?54+t5rab?= Date: Sun, 1 Aug 2021 17:47:46 +0800 Message-ID: Subject: Re: [PATCH v6 1/2] ASoC: sunxi: Add Allwinner H6 Digital MIC driver To: Maxime Ripard Cc: lgirdwood@gmail.com, Mark Brown , perex@perex.cz, tiwai@suse.com, wens@csie.org, jernej.skrabec@gmail.com, p.zabel@pengutronix.de, Samuel Holland , krzk@kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210801_024759_241864_EC42F18E X-CRM114-Status: GOOD ( 40.06 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGksIERlYXI6CgoKTWF4aW1lIFJpcGFyZCA8bWF4aW1lQGNlcm5vLnRlY2g+IOS6jjIwMjHlubQ3 5pyIMTXml6Xlkajlm5sg5LiL5Y2IMzo0N+WGmemBk++8mgoKPgo+IEhpCj4KPiBPbiBTdW4sIEp1 bCAxMSwgMjAyMSBhdCAwODoyMDo1NUFNIC0wNDAwLCBmZW5nemhlbmc5MjNAZ21haWwuY29tIHdy b3RlOgo+ID4gRnJvbTogQmFuIFRhbyA8ZmVuZ3poZW5nOTIzQGdtYWlsLmNvbT4KPiA+Cj4gPiBU aGUgQWxsd2lubmVyIEg2IGFuZCBsYXRlciBTb0NzIGhhdmUgYW4gRE1JQyBibG9jawo+ID4gd2hp Y2ggaXMgY2FwYWJsZSBvZiBjYXB0dXJlLgo+ID4KPiA+IFNpZ25lZC1vZmYtYnk6IEJhbiBUYW8g PGZlbmd6aGVuZzkyM0BnbWFpbC5jb20+Cj4gPgo+ID4gLS0tCj4gPiB2MS0+djI6Cj4gPiAxLkZp eCBzb21lIGNvbXBpbGF0aW9uIGVycm9ycy4KPiA+IDIuTW9kaWZ5IHNvbWUgY29kZSBzdHlsZXMu Cj4gPiAtLS0KPiA+IHYyLT52MzoKPiA+IE5vbmUuCj4gPiAtLS0KPiA+IHYzLT52NDoKPiA+IDEu YWRkIHNpZ19iaXRzLgo+ID4gLS0tCj4gPiB2NC0+djU6Cj4gPiBOb25lLgo+ID4gLS0tCj4gPiB2 NS0+djY6Cj4gPiAxLk1vZGlmeSBSWEZJRk9fQ1RMX01PREUgdG8gbW9kZSAxLgo+ID4gLS0tCj4g PiAgTUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgICAgfCAgIDcgKwo+ID4gIHNvdW5kL3NvYy9z dW54aS9LY29uZmlnICAgICAgIHwgICA4ICsKPiA+ICBzb3VuZC9zb2Mvc3VueGkvTWFrZWZpbGUg ICAgICB8ICAgMSArCj4gPiAgc291bmQvc29jL3N1bnhpL3N1bjUwaS1kbWljLmMgfCA0MDMgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ID4gIDQgZmlsZXMgY2hhbmdlZCwgNDE5 IGluc2VydGlvbnMoKykKPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQgc291bmQvc29jL3N1bnhpL3N1 bjUwaS1kbWljLmMKPiA+Cj4gPiBkaWZmIC0tZ2l0IGEvTUFJTlRBSU5FUlMgYi9NQUlOVEFJTkVS Uwo+ID4gaW5kZXggZTkyNGY5ZTVkZjk3Li44ZDcwMGJhYWEzY2EgMTAwNjQ0Cj4gPiAtLS0gYS9N QUlOVEFJTkVSUwo+ID4gKysrIGIvTUFJTlRBSU5FUlMKPiA+IEBAIC03NjAsNiArNzYwLDEzIEBA IEw6ICAgICAgIGxpbnV4LW1lZGlhQHZnZXIua2VybmVsLm9yZwo+ID4gIFM6ICAgTWFpbnRhaW5l ZAo+ID4gIEY6ICAgZHJpdmVycy9zdGFnaW5nL21lZGlhL3N1bnhpL2NlZHJ1cy8KPiA+Cj4gPiAr QUxMV0lOTkVSIERNSUMgRFJJVkVSUwo+ID4gK006ICAgQmFuIFRhbyA8ZmVuZ3poZW5nOTIzQGdt YWlsLmNvbT4KPiA+ICtMOiAgIGFsc2EtZGV2ZWxAYWxzYS1wcm9qZWN0Lm9yZyAobW9kZXJhdGVk IGZvciBub24tc3Vic2NyaWJlcnMpCj4gPiArUzogICBNYWludGFpbmVkCj4gPiArRjogICBEb2N1 bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3Mvc291bmQvYWxsd2lubmVyLHN1bjUwaS1oNi1k bWljLnlhbWwKPiA+ICtGOiAgIHNvdW5kL3NvYy9zdW54aS9zdW41MGktZG1pYy5jCj4gPiArCj4g PiAgQUxQSEEgUE9SVAo+ID4gIE06ICAgUmljaGFyZCBIZW5kZXJzb24gPHJ0aEB0d2lkZGxlLm5l dD4KPiA+ICBNOiAgIEl2YW4gS29rc2hheXNreSA8aW5rQGp1cmFzc2ljLnBhcmsubXN1LnJ1Pgo+ ID4gZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy9zdW54aS9LY29uZmlnIGIvc291bmQvc29jL3N1bnhp L0tjb25maWcKPiA+IGluZGV4IGRkY2FhYTk4ZDNjYi4uMmEzYmY3NzIyZTExIDEwMDY0NAo+ID4g LS0tIGEvc291bmQvc29jL3N1bnhpL0tjb25maWcKPiA+ICsrKyBiL3NvdW5kL3NvYy9zdW54aS9L Y29uZmlnCj4gPiBAQCAtNTYsNiArNTYsMTQgQEAgY29uZmlnIFNORF9TVU40SV9TUERJRgo+ID4g ICAgICAgICBTYXkgWSBvciBNIHRvIGFkZCBzdXBwb3J0IGZvciB0aGUgUy9QRElGIGF1ZGlvIGJs b2NrIGluIHRoZSBBbGx3aW5uZXIKPiA+ICAgICAgICAgQTEwIGFuZCBhZmZpbGlhdGVkIFNvQ3Mu Cj4gPgo+ID4gK2NvbmZpZyBTTkRfU1VONTBJX0RNSUMKPiA+ICsgICAgIHRyaXN0YXRlICJBbGx3 aW5uZXIgSDYgRE1JQyBTdXBwb3J0Igo+ID4gKyAgICAgZGVwZW5kcyBvbiAoT0YgJiYgQVJDSF9T VU5YSSkgfHwgQ09NUElMRV9URVNUCj4gPiArICAgICBzZWxlY3QgU05EX1NPQ19HRU5FUklDX0RN QUVOR0lORV9QQ00KPiA+ICsgICAgIGhlbHAKPiA+ICsgICAgICAgU2F5IFkgb3IgTSB0byBhZGQg c3VwcG9ydCBmb3IgdGhlIERNSUMgYXVkaW8gYmxvY2sgaW4gdGhlIEFsbHdpbm5lcgo+ID4gKyAg ICAgICBINiBhbmQgYWZmaWxpYXRlZCBTb0NzLgo+ID4gKwo+ID4gIGNvbmZpZyBTTkRfU1VOOElf QUREQV9QUl9SRUdNQVAKPiA+ICAgICAgIHRyaXN0YXRlCj4gPiAgICAgICBzZWxlY3QgUkVHTUFQ Cj4gPiBkaWZmIC0tZ2l0IGEvc291bmQvc29jL3N1bnhpL01ha2VmaWxlIGIvc291bmQvc29jL3N1 bnhpL01ha2VmaWxlCj4gPiBpbmRleCBhODZiZTM0MGEwNzYuLjQ0ODNmZTljOTRlZiAxMDA2NDQK PiA+IC0tLSBhL3NvdW5kL3NvYy9zdW54aS9NYWtlZmlsZQo+ID4gKysrIGIvc291bmQvc29jL3N1 bnhpL01ha2VmaWxlCj4gPiBAQCAtNiwzICs2LDQgQEAgb2JqLSQoQ09ORklHX1NORF9TVU44SV9D T0RFQ19BTkFMT0cpICs9IHN1bjhpLWNvZGVjLWFuYWxvZy5vCj4gPiAgb2JqLSQoQ09ORklHX1NO RF9TVU41MElfQ09ERUNfQU5BTE9HKSArPSBzdW41MGktY29kZWMtYW5hbG9nLm8KPiA+ICBvYmot JChDT05GSUdfU05EX1NVTjhJX0NPREVDKSArPSBzdW44aS1jb2RlYy5vCj4gPiAgb2JqLSQoQ09O RklHX1NORF9TVU44SV9BRERBX1BSX1JFR01BUCkgKz0gc3VuOGktYWRkYS1wci1yZWdtYXAubwo+ ID4gK29iai0kKENPTkZJR19TTkRfU1VONTBJX0RNSUMpICs9IHN1bjUwaS1kbWljLm8KPiA+IGRp ZmYgLS1naXQgYS9zb3VuZC9zb2Mvc3VueGkvc3VuNTBpLWRtaWMuYyBiL3NvdW5kL3NvYy9zdW54 aS9zdW41MGktZG1pYy5jCj4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+ID4gaW5kZXggMDAwMDAw MDAwMDAwLi5iYmFjODM2YmE0ZGUKPiA+IC0tLSAvZGV2L251bGwKPiA+ICsrKyBiL3NvdW5kL3Nv Yy9zdW54aS9zdW41MGktZG1pYy5jCj4gPiBAQCAtMCwwICsxLDQwMyBAQAo+ID4gKy8vIFNQRFgt TGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCj4gPiArLy8KPiA+ICsvLyBUaGlz IGRyaXZlciBzdXBwb3J0cyB0aGUgRE1JQyBpbiBBbGx3aW5uZXIncyBINiBTb0NzLgo+ID4gKy8v Cj4gPiArLy8gQ29weXJpZ2h0IDIwMjEgQmFuIFRhbyA8ZmVuZ3poZW5nOTIzQGdtYWlsLmNvbT4K PiA+ICsKPiA+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L2Rl dmljZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KPiA+ICsjaW5jbHVkZSA8 bGludXgvbW9kdWxlLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ ID4gKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3Jl c2V0Lmg+Cj4gPiArI2luY2x1ZGUgPHNvdW5kL2RtYWVuZ2luZV9wY20uaD4KPiA+ICsjaW5jbHVk ZSA8c291bmQvcGNtX3BhcmFtcy5oPgo+ID4gKyNpbmNsdWRlIDxzb3VuZC9zb2MuaD4KPiA+ICsK PiA+ICsjZGVmaW5lIFNVTjUwSV9ETUlDX0VOX0NUTCAgICAgICAgICAgKDB4MDApCj4gPiArICAg ICAjZGVmaW5lIFNVTjUwSV9ETUlDX0VOX0NUTF9HTE9CRSAgICAgICAgICAgICAgICAgICAgICAg IEJJVCg4KQo+ID4gKyAgICAgI2RlZmluZSBTVU41MElfRE1JQ19FTl9DVExfQ0hBTih2KSAgICAg ICAgICAgICAgKCh2KSA8PCAwKQo+ID4gKyAgICAgI2RlZmluZSBTVU41MElfRE1JQ19FTl9DVExf Q0hBTl9NQVNLICAgICAgICAgICAgR0VOTUFTSyg3LCAwKQo+ID4gKyNkZWZpbmUgU1VONTBJX0RN SUNfU1IgICAgICAgICAgICAgICAgICAgICAgICgweDA0KQo+ID4gKyAgICAgI2RlZmluZSBTVU41 MElfRE1JQ19TUl9TQU1QTEVfUkFURSh2KSAgICAgICAgICAgKCh2KSA8PCAwKQo+ID4gKyAgICAg I2RlZmluZSBTVU41MElfRE1JQ19TUl9TQU1QTEVfUkFURV9NQVNLICAgICAgICAgR0VOTUFTSygy LCAwKQo+ID4gKyNkZWZpbmUgU1VONTBJX0RNSUNfQ1RMICAgICAgICAgICAgICAgICAgICAgICgw eDA4KQo+ID4gKyAgICAgI2RlZmluZSBTVU41MElfRE1JQ19DVExfT1ZFUlNBTVBMRV9SQVRFICAg ICAgICAgQklUKDApCj4gPiArI2RlZmluZSBTVU41MElfRE1JQ19EQVRBICAgICAgICAgICAgICAg ICAgICAgKDB4MTApCj4gPiArI2RlZmluZSBTVU41MElfRE1JQ19JTlRDICAgICAgICAgICAgICAg ICAgICAgKDB4MTQpCj4gPiArICAgICAjZGVmaW5lIFNVTjUwSV9ETUlDX0ZJRk9fRFJRX0VOICAg ICAgICAgICAgICAgICBCSVQoMikKPiA+ICsjZGVmaW5lIFNVTjUwSV9ETUlDX0lOVF9TVEEgICAg ICAgICAgKDB4MTgpCj4gPiArICAgICAjZGVmaW5lIFNVTjUwSV9ETUlDX0lOVF9TVEFfT1ZFUlJV Tl9JUlFfUEVORElORyBCSVQoMSkKPiA+ICsgICAgICNkZWZpbmUgU1VONTBJX0RNSUNfSU5UX1NU QV9EQVRBX0lSUV9QRU5ESU5HICAgIEJJVCgwKQo+ID4gKyNkZWZpbmUgU1VONTBJX0RNSUNfUlhG SUZPX0NUTCAgICAgICAgICAgICAgICgweDFjKQo+ID4gKyAgICAgI2RlZmluZSBTVU41MElfRE1J Q19SWEZJRk9fQ1RMX0ZMVVNIICAgICAgICAgICAgQklUKDMxKQo+ID4gKyAgICAgI2RlZmluZSBT VU41MElfRE1JQ19SWEZJRk9fQ1RMX01PREUgICAgICAgICAgICAgQklUKDkpCj4gPiArICAgICAj ZGVmaW5lIFNVTjUwSV9ETUlDX1JYRklGT19DVExfUkVTT0xVVElPTiAgICAgICBCSVQoOCkKPiA+ ICsjZGVmaW5lIFNVTjUwSV9ETUlDX0NIX05VTSAgICAgICAgICAgKDB4MjQpCj4gPiArICAgICAj ZGVmaW5lIFNVTjUwSV9ETUlDX0NIX05VTV9OKHYpICAgICAgICAgICAgICAgICAoKHYpIDw8IDAp Cj4gPiArICAgICAjZGVmaW5lIFNVTjUwSV9ETUlDX0NIX05VTV9OX01BU0sgICAgICAgICAgICAg ICBHRU5NQVNLKDIsIDApCj4gPiArI2RlZmluZSBTVU41MElfRE1JQ19DTlQgICAgICAgICAgICAg ICAgICAgICAgKDB4MmMpCj4gPiArICAgICAjZGVmaW5lIFNVTjUwSV9ETUlDX0NOVF9OICAgICAg ICAgICAgICAgICAgICAgICBCSVQoMCkKPiA+ICsjZGVmaW5lIFNVTjUwSV9ETUlDX0hQRl9DVFJM ICAgICAgICAgKDB4MzgpCj4gPiArI2RlZmluZSBTVU41MElfRE1JQ19WRVJTSU9OICAgICAgICAg ICgweDUwKQo+ID4gKwo+ID4gKwo+Cj4gVGhlcmUncyBtdWx0aXBsZSBibGFuayBsaW5lcyBoZXJl Cj4KPiA+ICtzdHJ1Y3Qgc3VuNTBpX2RtaWNfZGV2IHsKPiA+ICsgICAgIHN0cnVjdCBjbGsgKmRt aWNfY2xrOwo+ID4gKyAgICAgc3RydWN0IGNsayAqYnVzX2NsazsKPiA+ICsgICAgIHN0cnVjdCBy ZXNldF9jb250cm9sICpyc3Q7Cj4gPiArICAgICBzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7Cj4gPiAr ICAgICBzdHJ1Y3Qgc25kX2RtYWVuZ2luZV9kYWlfZG1hX2RhdGEgZG1hX3BhcmFtc19yeDsKPiA+ ICsgICAgIHVuc2lnbmVkIGludCBjaGFuX2VuOwo+ID4gK307Cj4gPiArCj4gPiArc3RydWN0IGRt aWNfcmF0ZSB7Cj4gPiArICAgICB1bnNpZ25lZCBpbnQgc2FtcGxlcmF0ZTsKPiA+ICsgICAgIHVu c2lnbmVkIGludCByYXRlX2JpdDsKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgc3VuNTBp X2RtaWNfc3RhcnR1cChzdHJ1Y3Qgc25kX3BjbV9zdWJzdHJlYW0gKnN1YnN0cmVhbSwKPiA+ICsg ICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHNuZF9zb2NfZGFpICpjcHVfZGFpKQo+ ID4gK3sKPiA+ICsgICAgIHN0cnVjdCBzbmRfc29jX3BjbV9ydW50aW1lICpydGQgPSBzdWJzdHJl YW0tPnByaXZhdGVfZGF0YTsKPiA+ICsgICAgIHN0cnVjdCBzdW41MGlfZG1pY19kZXYgKmhvc3Qg PSBzbmRfc29jX2RhaV9nZXRfZHJ2ZGF0YShhc29jX3J0ZF90b19jcHUocnRkLCAwKSk7Cj4gPiAr Cj4gPiArICAgICAvKiBvbmx5IHN1cHBvcnQgY2FwdHVyZSAqLwo+ID4gKyAgICAgaWYgKHN1YnN0 cmVhbS0+c3RyZWFtICE9IFNORFJWX1BDTV9TVFJFQU1fQ0FQVFVSRSkKPiA+ICsgICAgICAgICAg ICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArCj4gPiArICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaG9z dC0+cmVnbWFwLCBTVU41MElfRE1JQ19SWEZJRk9fQ1RMLAo+ID4gKyAgICAgICAgICAgICAgICAg ICAgICAgIFNVTjUwSV9ETUlDX1JYRklGT19DVExfRkxVU0gsCj4gPiArICAgICAgICAgICAgICAg ICAgICAgICAgU1VONTBJX0RNSUNfUlhGSUZPX0NUTF9GTFVTSCk7Cj4gPiArICAgICByZWdtYXBf d3JpdGUoaG9zdC0+cmVnbWFwLCBTVU41MElfRE1JQ19DTlQsIFNVTjUwSV9ETUlDX0NOVF9OKTsK PiA+ICsKPiA+ICsgICAgIHJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IHN1 bjUwaV9kbWljX2h3X3BhcmFtcyhzdHJ1Y3Qgc25kX3BjbV9zdWJzdHJlYW0gKnN1YnN0cmVhbSwK PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgc25kX3BjbV9od19wYXJh bXMgKnBhcmFtcywKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgc25k X3NvY19kYWkgKmNwdV9kYWkpCj4gPiArewo+ID4gKyAgICAgaW50IGkgPSAwOwo+ID4gKyAgICAg dW5zaWduZWQgbG9uZyByYXRlID0gcGFyYW1zX3JhdGUocGFyYW1zKTsKPiA+ICsgICAgIHVuc2ln bmVkIGludCBtY2xrID0gMDsKPiA+ICsgICAgIHVuc2lnbmVkIGludCBjaGFubmVscyA9IHBhcmFt c19jaGFubmVscyhwYXJhbXMpOwo+ID4gKyAgICAgc3RydWN0IHN1bjUwaV9kbWljX2RldiAqaG9z dCA9IHNuZF9zb2NfZGFpX2dldF9kcnZkYXRhKGNwdV9kYWkpOwo+ID4gKyAgICAgc3RhdGljIHN0 cnVjdCBkbWljX3JhdGUgZG1pY19yYXRlX3NbXSA9IHsKPiA+ICsgICAgICAgICAgICAgezQ0MTAw LCAweDB9LAo+ID4gKyAgICAgICAgICAgICB7NDgwMDAsIDB4MH0sCj4gPiArICAgICAgICAgICAg IHsyMjA1MCwgMHgyfSwKPiA+ICsgICAgICAgICAgICAgezI0MDAwLCAweDJ9LAo+ID4gKyAgICAg ICAgICAgICB7MTEwMjUsIDB4NH0sCj4gPiArICAgICAgICAgICAgIHsxMjAwMCwgMHg0fSwKPiA+ ICsgICAgICAgICAgICAgezMyMDAwLCAweDF9LAo+ID4gKyAgICAgICAgICAgICB7MTYwMDAsIDB4 M30sCj4gPiArICAgICAgICAgICAgIHs4MDAwLCAgMHg1fSwKPiA+ICsgICAgIH07Cj4KPiBXZSBz aG91bGQgb3JkZXIgdGhlc2UgaXRlbXMuIEl0IGxvb2tzIGxpa2UgZGVzY2VuZGluZyByYXRlIG1h a2VzIHRoZQo+IG1vc3Qgc2Vuc2U/Cj4KPiBBbHNvLCBJJ20gbm90IHN1cmUgd2h5IHdlIG5lZWQg dG8gbWFrZSB0aGF0IGFycmF5IGxvY2FsLCBjYW4ndCB0aGlzIGJlIGEKPiBnbG9iYWwgdmFyaWFi bGU/Cj4KPiA+ICsgICAgIC8qIERNSUMgbnVtIGlzIE4rMSAqLwo+ID4gKyAgICAgcmVnbWFwX3Vw ZGF0ZV9iaXRzKGhvc3QtPnJlZ21hcCwgU1VONTBJX0RNSUNfQ0hfTlVNLAo+ID4gKyAgICAgICAg ICAgICAgICAgICAgICAgIFNVTjUwSV9ETUlDX0NIX05VTV9OX01BU0ssCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICAgU1VONTBJX0RNSUNfQ0hfTlVNX04oY2hhbm5lbHMgLSAxKSk7Cj4gPiAr ICAgICBob3N0LT5jaGFuX2VuID0gKDEgPDwgY2hhbm5lbHMpIC0gMTsKPiA+ICsgICAgIHJlZ21h cF93cml0ZShob3N0LT5yZWdtYXAsIFNVTjUwSV9ETUlDX0hQRl9DVFJMLCBob3N0LT5jaGFuX2Vu KTsKPgo+IERvIHdlIG5lZWQgdG8gc3RvcmUgdGhlIGNoYW5uZWxzIGJpdG1hc2sgaW4gdGhlIG1h aW4gc3RydWN0dXJlPyBJdCBsb29rcwo+IGZhaXJseSBlYXN5IHRvIGdlbmVyYXRlLCBzbyBJIGd1 ZXNzIHdlIGNvdWxkIGp1c3QgdXNlIGEgbWFjcm8KCkkgbmVlZCB0byBzdG9yZSBjaGFubmVscyBi aXRtYXNrIGFuZCB1c2UgaXQgaW4gc3VuNTBpX2RtaWNfdHJpZ2dlciBmdW5jdGlvbi4KCj4KPiA+ ICsgICAgIHN3aXRjaCAocGFyYW1zX2Zvcm1hdChwYXJhbXMpKSB7Cj4gPiArICAgICBjYXNlIFNO RFJWX1BDTV9GT1JNQVRfUzE2X0xFOgo+ID4gKyAgICAgICAgICAgICByZWdtYXBfdXBkYXRlX2Jp dHMoaG9zdC0+cmVnbWFwLCBTVU41MElfRE1JQ19SWEZJRk9fQ1RMLAo+ID4gKyAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgU1VONTBJX0RNSUNfUlhGSUZPX0NUTF9SRVNPTFVUSU9OLCAw KTsKPiA+ICsgICAgICAgICAgICAgYnJlYWs7Cj4gPiArICAgICBjYXNlIFNORFJWX1BDTV9GT1JN QVRfUzI0X0xFOgo+ID4gKyAgICAgICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaG9zdC0+cmVn bWFwLCBTVU41MElfRE1JQ19SWEZJRk9fQ1RMLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgU1VONTBJX0RNSUNfUlhGSUZPX0NUTF9SRVNPTFVUSU9OLAo+ID4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgU1VONTBJX0RNSUNfUlhGSUZPX0NUTF9SRVNPTFVUSU9O KTsKPiA+ICsgICAgICAgICAgICAgYnJlYWs7Cj4KPiBUaGVzZSB0d28gZGVmaW5lcyBjb3VsZCBi ZSBuYW1lZCBhIGJpdCBiZXR0ZXIsIGl0J3Mgbm90IHJlYWxseSBjbGVhcgo+IHdoYXQgU1VONTBJ X0RNSUNfUlhGSUZPX0NUTF9SRVNPTFVUSU9OIG1lYW5zLCBleGFjdGx5LCBhcyBvcHBvc2VkIHRv IDAKPiAod2hpbGUgaXQncyBhY3R1YWxseSB0aGUgc2FtcGxlIHdpZHRoKS4KPgo+IFdoYXQgYWJv dXQgc29tZXRoaW5nIGxpa2UgU1VONTBJX0RNSUNfUlhGSUZPX0NUTF9TQU1QTEVfMTYgKGZvciAw KSBhbmQKPiBfMjQgKGZvciAxKSwgd2hpbGUgY2hhbmdpbmcgU1VONTBJX0RNSUNfUlhGSUZPX0NU TF9SRVNPTFVUSU9OIGZvcgo+IFNVTjUwSV9ETUlDX1JYRklGT19DVExfU0FNUExFX01BU0sgPwo+ Cj4gPiArICAgICBkZWZhdWx0Ogo+ID4gKyAgICAgICAgICAgICBkZXZfZXJyKGNwdV9kYWktPmRl diwgIkludmFsaWQgZm9ybWF0IVxuIik7Cj4gPiArICAgICAgICAgICAgIHJldHVybiAtRUlOVkFM Owo+ID4gKyAgICAgfQo+ID4gKyAgICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGhvc3QtPnJlZ21hcCwg U1VONTBJX0RNSUNfUlhGSUZPX0NUTCwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICBTVU41 MElfRE1JQ19SWEZJRk9fQ1RMX01PREUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgU1VO NTBJX0RNSUNfUlhGSUZPX0NUTF9NT0RFKTsKPgo+IFNhbWUgdGhpbmcgaGVyZSwgTU9ERSBkb2Vz bid0IHJlYWxseSBleHBsYWluIHdoYXQgdGhpcyBkb2VzLCBhbmQgd2h5Cj4gd2UnZCB3YW50IHRv IGFsd2F5cyBzZXQgaXQuCj4KPiBJIGd1ZXNzIDAgaXMgTFNCX1pFUk8gYW5kIDEgaXMgTVNCX1NJ R04/CgpZZXMuCgo+Cj4gPiArICAgICBzd2l0Y2ggKHJhdGUpIHsKPiA+ICsgICAgIGNhc2UgMTEw MjU6Cj4gPiArICAgICBjYXNlIDIyMDUwOgo+ID4gKyAgICAgY2FzZSA0NDEwMDoKPiA+ICsgICAg ICAgICAgICAgbWNsayA9IDIyNTc5MjAwOwo+ID4gKyAgICAgICAgICAgICBicmVhazsKPiA+ICsg ICAgIGNhc2UgODAwMDoKPiA+ICsgICAgIGNhc2UgMTIwMDA6Cj4gPiArICAgICBjYXNlIDE2MDAw Ogo+ID4gKyAgICAgY2FzZSAyNDAwMDoKPiA+ICsgICAgIGNhc2UgMzIwMDA6Cj4gPiArICAgICBj YXNlIDQ4MDAwOgo+ID4gKyAgICAgICAgICAgICBtY2xrID0gMjQ1NzYwMDA7Cj4gPiArICAgICAg ICAgICAgIGJyZWFrOwo+ID4gKyAgICAgZGVmYXVsdDoKPiA+ICsgICAgICAgICAgICAgZGV2X2Vy cihjcHVfZGFpLT5kZXYsICJJbnZhbGlkIHJhdGUhXG4iKTsKPiA+ICsgICAgICAgICAgICAgcmV0 dXJuIC1FSU5WQUw7Cj4gPiArICAgICB9Cj4gPiArCj4gPiArICAgICBpZiAoY2xrX3NldF9yYXRl KGhvc3QtPmRtaWNfY2xrLCBtY2xrKSkgewo+ID4gKyAgICAgICAgICAgICBkZXZfZXJyKGNwdV9k YWktPmRldiwgIm1jbGsgOiAldSBub3Qgc3VwcG9ydFxuIiwgbWNsayk7Cj4gPiArICAgICAgICAg ICAgIHJldHVybiAtRUlOVkFMOwo+ID4gKyAgICAgfQo+ID4gKwo+ID4gKyAgICAgZm9yIChpID0g MDsgaSA8IEFSUkFZX1NJWkUoZG1pY19yYXRlX3MpOyBpKyspIHsKPiA+ICsgICAgICAgICAgICAg aWYgKGRtaWNfcmF0ZV9zW2ldLnNhbXBsZXJhdGUgPT0gcmF0ZSkgewo+ID4gKyAgICAgICAgICAg ICAgICAgICAgIHJlZ21hcF91cGRhdGVfYml0cyhob3N0LT5yZWdtYXAsIFNVTjUwSV9ETUlDX1NS LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVU41MElfRE1J Q19TUl9TQU1QTEVfUkFURV9NQVNLLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBTVU41MElfRE1JQ19TUl9TQU1QTEVfUkFURShkbWljX3JhdGVfc1tpXS5yYXRl X2JpdCkpOwo+ID4gKyAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwo+ID4gKyAgICAgICAgICAg ICB9Cj4gPiArICAgICB9Cj4gPiArCj4gPiArICAgICBzd2l0Y2ggKHBhcmFtc19waHlzaWNhbF93 aWR0aChwYXJhbXMpKSB7Cj4gPiArICAgICBjYXNlIDE2Ogo+ID4gKyAgICAgICAgICAgICBob3N0 LT5kbWFfcGFyYW1zX3J4LmFkZHJfd2lkdGggPSBETUFfU0xBVkVfQlVTV0lEVEhfMl9CWVRFUzsK PiA+ICsgICAgICAgICAgICAgYnJlYWs7Cj4gPiArICAgICBjYXNlIDMyOgo+ID4gKyAgICAgICAg ICAgICBob3N0LT5kbWFfcGFyYW1zX3J4LmFkZHJfd2lkdGggPSBETUFfU0xBVkVfQlVTV0lEVEhf NF9CWVRFUzsKPiA+ICsgICAgICAgICAgICAgYnJlYWs7Cj4gPiArICAgICBkZWZhdWx0Ogo+ID4g KyAgICAgICAgICAgICBkZXZfZXJyKGNwdV9kYWktPmRldiwgIlVuc3VwcG9ydGVkIHBoeXNpY2Fs IHNhbXBsZSB3aWR0aDogJWRcbiIsCj4gPiArICAgICAgICAgICAgICAgICAgICAgcGFyYW1zX3Bo eXNpY2FsX3dpZHRoKHBhcmFtcykpOwo+ID4gKyAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsK PiA+ICsgICAgIH0KPiA+ICsKPiA+ICsgICAgIC8qIG92ZXJzYW1wbGVyYXRlIGFkanVzdCAqLwo+ ID4gKyAgICAgaWYgKHBhcmFtc19yYXRlKHBhcmFtcykgPj0gMjQwMDApCj4gPiArICAgICAgICAg ICAgIHJlZ21hcF91cGRhdGVfYml0cyhob3N0LT5yZWdtYXAsIFNVTjUwSV9ETUlDX0NUTCwKPiA+ ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNVTjUwSV9ETUlDX0NUTF9PVkVSU0FN UExFX1JBVEUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVU41MElfRE1J Q19DVExfT1ZFUlNBTVBMRV9SQVRFKTsKPiA+ICsgICAgIGVsc2UKPiA+ICsgICAgICAgICAgICAg cmVnbWFwX3VwZGF0ZV9iaXRzKGhvc3QtPnJlZ21hcCwgU1VONTBJX0RNSUNfQ1RMLAo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VONTBJX0RNSUNfQ1RMX09WRVJTQU1QTEVf UkFURSwgMCk7Cj4gPiArCj4gPiArICAgICByZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3Rh dGljIGludCBzdW41MGlfZG1pY190cmlnZ2VyKHN0cnVjdCBzbmRfcGNtX3N1YnN0cmVhbSAqc3Vi c3RyZWFtLCBpbnQgY21kLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qg c25kX3NvY19kYWkgKmRhaSkKPiA+ICt7Cj4gPiArICAgICBpbnQgcmV0ID0gMDsKPiA+ICsgICAg IHN0cnVjdCBzdW41MGlfZG1pY19kZXYgKmhvc3QgPSBzbmRfc29jX2RhaV9nZXRfZHJ2ZGF0YShk YWkpOwo+ID4gKwo+ID4gKyAgICAgaWYgKHN1YnN0cmVhbS0+c3RyZWFtICE9IFNORFJWX1BDTV9T VFJFQU1fQ0FQVFVSRSkKPiA+ICsgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArCj4g PiArICAgICBzd2l0Y2ggKGNtZCkgewo+ID4gKyAgICAgY2FzZSBTTkRSVl9QQ01fVFJJR0dFUl9T VEFSVDoKPiA+ICsgICAgIGNhc2UgU05EUlZfUENNX1RSSUdHRVJfUkVTVU1FOgo+ID4gKyAgICAg Y2FzZSBTTkRSVl9QQ01fVFJJR0dFUl9QQVVTRV9SRUxFQVNFOgo+ID4gKyAgICAgICAgICAgICAv KiBEUlEgRU5BQkxFICovCj4gPiArICAgICAgICAgICAgIHJlZ21hcF91cGRhdGVfYml0cyhob3N0 LT5yZWdtYXAsIFNVTjUwSV9ETUlDX0lOVEMsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBTVU41MElfRE1JQ19GSUZPX0RSUV9FTiwKPiA+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIFNVTjUwSV9ETUlDX0ZJRk9fRFJRX0VOKTsKPiA+ICsgICAgICAgICAgICAg cmVnbWFwX3VwZGF0ZV9iaXRzKGhvc3QtPnJlZ21hcCwgU1VONTBJX0RNSUNfRU5fQ1RMLAo+ID4g KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VONTBJX0RNSUNfRU5fQ1RMX0NIQU5f TUFTSywKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNVTjUwSV9ETUlDX0VO X0NUTF9DSEFOKGhvc3QtPmNoYW5fZW4pKTsKPiA+ICsgICAgICAgICAgICAgLyogR2xvYmFsIGVu YWJsZSAqLwo+ID4gKyAgICAgICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaG9zdC0+cmVnbWFw LCBTVU41MElfRE1JQ19FTl9DVEwsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBTVU41MElfRE1JQ19FTl9DVExfR0xPQkUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBTVU41MElfRE1JQ19FTl9DVExfR0xPQkUpOwo+ID4gKyAgICAgICAgICAgICBicmVh azsKPgo+IERvIHdlIHJlYWxseSBuZWVkIHRvIGNsZWFyIHRoZSBjaGFubmVsIGFuZCBnbG9iYWwg ZW5hYmxlIGJpdHM/IGFuZCBEUlE/CgpXaHkgbm90PyBJIHRoaW5rIHdlIHNob3VsZCBjbGVhciB0 aGVtIHdoZW4gbm90IGluIHVzZS4uLi4uLgoKPgo+ID4gKyAgICAgY2FzZSBTTkRSVl9QQ01fVFJJ R0dFUl9TVE9QOgo+ID4gKyAgICAgY2FzZSBTTkRSVl9QQ01fVFJJR0dFUl9TVVNQRU5EOgo+ID4g KyAgICAgY2FzZSBTTkRSVl9QQ01fVFJJR0dFUl9QQVVTRV9QVVNIOgo+ID4gKyAgICAgICAgICAg ICAvKiBEUlEgRElTQUJMRSAqLwo+ID4gKyAgICAgICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMo aG9zdC0+cmVnbWFwLCBTVU41MElfRE1JQ19JTlRDLAo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgU1VONTBJX0RNSUNfRklGT19EUlFfRU4sIDApOwo+ID4gKyAgICAgICAgICAg ICByZWdtYXBfdXBkYXRlX2JpdHMoaG9zdC0+cmVnbWFwLCBTVU41MElfRE1JQ19FTl9DVEwsCj4g PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVU41MElfRE1JQ19FTl9DVExfQ0hB Tl9NQVNLLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VONTBJX0RNSUNf RU5fQ1RMX0NIQU4oMCkpOwo+ID4gKyAgICAgICAgICAgICAvKiBHbG9iYWwgZGlzYWJsZSAqLwo+ ID4gKyAgICAgICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaG9zdC0+cmVnbWFwLCBTVU41MElf RE1JQ19FTl9DVEwsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVU41MElf RE1JQ19FTl9DVExfR0xPQkUsIDApOwo+ID4gKyAgICAgICAgICAgICBicmVhazsKPiA+ICsKPiA+ ICsgICAgIGRlZmF1bHQ6Cj4gPiArICAgICAgICAgICAgIHJldCA9IC1FSU5WQUw7Cj4gPiArICAg ICAgICAgICAgIGJyZWFrOwo+ID4gKyAgICAgfQo+ID4gKyAgICAgcmV0dXJuIHJldDsKPiA+ICt9 Cj4gPiArCj4gPiArc3RhdGljIGludCBzdW41MGlfZG1pY19zb2NfZGFpX3Byb2JlKHN0cnVjdCBz bmRfc29jX2RhaSAqZGFpKQo+ID4gK3sKPiA+ICsgICAgIHN0cnVjdCBzdW41MGlfZG1pY19kZXYg Kmhvc3QgPSBzbmRfc29jX2RhaV9nZXRfZHJ2ZGF0YShkYWkpOwo+ID4gKwo+ID4gKyAgICAgc25k X3NvY19kYWlfaW5pdF9kbWFfZGF0YShkYWksIE5VTEwsICZob3N0LT5kbWFfcGFyYW1zX3J4KTsK PiA+ICsKPiA+ICsgICAgIHJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qg c3RydWN0IHNuZF9zb2NfZGFpX29wcyBzdW41MGlfZG1pY19kYWlfb3BzID0gewo+ID4gKyAgICAg LnN0YXJ0dXAgICAgICAgID0gc3VuNTBpX2RtaWNfc3RhcnR1cCwKPiA+ICsgICAgIC50cmlnZ2Vy ICAgICAgICA9IHN1bjUwaV9kbWljX3RyaWdnZXIsCj4gPiArICAgICAuaHdfcGFyYW1zICAgICAg PSBzdW41MGlfZG1pY19od19wYXJhbXMsCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qg c3RydWN0IHJlZ21hcF9jb25maWcgc3VuNTBpX2RtaWNfcmVnbWFwX2NvbmZpZyA9IHsKPiA+ICsg ICAgIC5yZWdfYml0cyA9IDMyLAo+ID4gKyAgICAgLnJlZ19zdHJpZGUgPSA0LAo+ID4gKyAgICAg LnZhbF9iaXRzID0gMzIsCj4gPiArICAgICAubWF4X3JlZ2lzdGVyID0gU1VONTBJX0RNSUNfVkVS U0lPTiwKPiA+ICsgICAgIC5jYWNoZV90eXBlID0gUkVHQ0FDSEVfTk9ORSwKPiA+ICt9Owo+ID4g Kwo+ID4gKyNkZWZpbmUgICAgICBTVU41MElfRE1JQ19SQVRFUyAoU05EUlZfUENNX1JBVEVfODAw MF80ODAwMCkKPiA+ICsjZGVmaW5lIFNVTjUwSV9GT1JNQVRTICAgICAgIChTTkRSVl9QQ01fRk1U QklUX1MxNl9MRSB8IFNORFJWX1BDTV9GTVRCSVRfUzI0X0xFKQo+Cj4gU1VONTBJX0RNSUNfUkFU RVMgaGFzIGEgdGFiIGJldHdlZW4gdGhlIGRlZmluZSBhbmQgaXRzIG5hbWUsIHdoaWxlCj4gU1VO NTBJX0ZPUk1BVFMgaGFzIHRoZSB0YWIgYWZ0ZXIgdGhlIG5hbWUuIFdlIHNob3VsZCBiZSBjb25z aXN0ZW50Lgo+IFNpbWlsYXJseSwgd2Ugc2hvdWxkIG5hbWUgYm90aCB3aXRoIHRoZSBTVU41MElf RE1JQyBwcmVmaXguCj4KPiA+ICtzdGF0aWMgc3RydWN0IHNuZF9zb2NfZGFpX2RyaXZlciBzdW41 MGlfZG1pY19kYWkgPSB7Cj4gPiArICAgICAuY2FwdHVyZSA9IHsKPiA+ICsgICAgICAgICAgICAg LmNoYW5uZWxzX21pbiA9IDEsCj4gPiArICAgICAgICAgICAgIC5jaGFubmVsc19tYXggPSA4LAo+ ID4gKyAgICAgICAgICAgICAucmF0ZXMgPSBTVU41MElfRE1JQ19SQVRFUywKPiA+ICsgICAgICAg ICAgICAgLmZvcm1hdHMgPSBTVU41MElfRk9STUFUUywKPiA+ICsgICAgICAgICAgICAgLnNpZ19i aXRzID0gMjEsCj4gPiArICAgICB9LAo+ID4gKyAgICAgLnByb2JlID0gc3VuNTBpX2RtaWNfc29j X2RhaV9wcm9iZSwKPiA+ICsgICAgIC5vcHMgPSAmc3VuNTBpX2RtaWNfZGFpX29wcywKPiA+ICsg ICAgIC5uYW1lID0gImRtaWMiLAo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVj dCBvZl9kZXZpY2VfaWQgc3VuNTBpX2RtaWNfb2ZfbWF0Y2hbXSA9IHsKPiA+ICsgICAgIHsKPiA+ ICsgICAgICAgICAgICAgLmNvbXBhdGlibGUgPSAiYWxsd2lubmVyLHN1bjUwaS1oNi1kbWljIiwK PiA+ICsgICAgIH0sCj4gPiArICAgICB7IC8qIHNlbnRpbmVsICovIH0KPiA+ICt9Owo+ID4gK01P RFVMRV9ERVZJQ0VfVEFCTEUob2YsIHN1bjUwaV9kbWljX29mX21hdGNoKTsKPiA+ICsKPiA+ICtz dGF0aWMgY29uc3Qgc3RydWN0IHNuZF9zb2NfY29tcG9uZW50X2RyaXZlciBzdW41MGlfZG1pY19j b21wb25lbnQgPSB7Cj4gPiArICAgICAubmFtZSAgICAgICAgICAgPSAic3VuNTBpLWRtaWMiLAo+ ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGludCBzdW41MGlfZG1pY19ydW50aW1lX3N1c3BlbmQo c3RydWN0IGRldmljZSAqZGV2KQo+ID4gK3sKPiA+ICsgICAgIHN0cnVjdCBzdW41MGlfZG1pY19k ZXYgKmhvc3QgID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gPiArCj4gPiArICAgICBjbGtfZGlz YWJsZV91bnByZXBhcmUoaG9zdC0+ZG1pY19jbGspOwo+ID4gKyAgICAgY2xrX2Rpc2FibGVfdW5w cmVwYXJlKGhvc3QtPmJ1c19jbGspOwo+ID4gKwo+ID4gKyAgICAgcmV0dXJuIDA7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgc3VuNTBpX2RtaWNfcnVudGltZV9yZXN1bWUoc3RydWN0IGRl dmljZSAqZGV2KQo+ID4gK3sKPiA+ICsgICAgIHN0cnVjdCBzdW41MGlfZG1pY19kZXYgKmhvc3Qg ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gPiArICAgICBpbnQgcmV0Owo+ID4gKwo+ID4gKyAg ICAgcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGhvc3QtPmRtaWNfY2xrKTsKPiA+ICsgICAgIGlm IChyZXQpCj4gPiArICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4KPiBBIG5ldyBsaW5lIGhlcmUg d291bGQgYmUgZ3JlYXQuCj4KPiA+ICsgICAgIHJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShob3N0 LT5idXNfY2xrKTsKPiA+ICsgICAgIGlmIChyZXQpCj4gPiArICAgICAgICAgICAgIGNsa19kaXNh YmxlX3VucHJlcGFyZShob3N0LT5kbWljX2Nsayk7Cj4gPiArCj4gPiArICAgICByZXR1cm4gcmV0 Owo+Cj4gSW4gZ2VuZXJhbCB3ZSBwcmVmZXIgdG8gdHJlYXQgdGhlIGVycm9yIHBhdGggYW5kIHRo ZSBzdWNjZXNzIHBhdGgKPiBkaWZmZXJlbnRseS4gSW4gdGhpcyBjYXNlIGl0IHdvdWxkIG1lYW4g Y2hhbmdpbmcgdGhhdCBwYXJ0IHRvCj4KPiByZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoaG9zdC0+ YnVzX2Nsayk7Cj4gaWYgKHJldCkgewo+ICAgICAgICAgIGNsa19kaXNhYmxlX3VucHJlcGFyZSho b3N0LT5kbWljX2Nsayk7Cj4gICAgICAgICAgcmV0dXJuIHJldDsKPiB9Cj4KPiByZXR1cm4gMDsK Pgo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IHN1bjUwaV9kbWljX3Byb2JlKHN0cnVjdCBw bGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gPiArewo+ID4gKyAgICAgc3RydWN0IHN1bjUwaV9kbWlj X2RldiAqaG9zdDsKPiA+ICsgICAgIHN0cnVjdCByZXNvdXJjZSAqcmVzOwo+ID4gKyAgICAgaW50 IHJldDsKPiA+ICsgICAgIHZvaWQgX19pb21lbSAqYmFzZTsKPiA+ICsKPiA+ICsgICAgIGhvc3Qg PSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCpob3N0KSwgR0ZQX0tFUk5FTCk7Cj4g PiArICAgICBpZiAoIWhvc3QpCj4gPiArICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOwo+ID4g Kwo+ID4gKyAgICAgLyogR2V0IHRoZSBhZGRyZXNzZXMgKi8KPiA+ICsgICAgIHJlcyA9IHBsYXRm b3JtX2dldF9yZXNvdXJjZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMCk7Cj4gPiArICAgICBiYXNl ID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIHJlcyk7Cj4gPiArICAgICBpZiAo SVNfRVJSKGJhc2UpKQo+ID4gKyAgICAgICAgICAgICByZXR1cm4gZGV2X2Vycl9wcm9iZSgmcGRl di0+ZGV2LCBQVFJfRVJSKGJhc2UpLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAiZ2V0IHJlc291cmNlIGZhaWxlZC5cbiIpOwo+ID4gKwo+ID4gKyAgICAgaG9zdC0+cmVn bWFwID0gZGV2bV9yZWdtYXBfaW5pdF9tbWlvKCZwZGV2LT5kZXYsIGJhc2UsCj4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJnN1bjUwaV9kbWljX3JlZ21h cF9jb25maWcpOwo+Cj4gWW91ciBzZWNvbmQgbGluZSBzaG91bGQgYmUgYWxpZ25lZCBvbiB0aGUg b3BlbmluZyBwYXJlbnRoZXNpcwo+Cj4gPiArICAgICAvKiBDbG9ja3MgKi8KPiA+ICsgICAgIGhv c3QtPmJ1c19jbGsgPSBkZXZtX2Nsa19nZXQoJnBkZXYtPmRldiwgImJ1cyIpOwo+ID4gKyAgICAg aWYgKElTX0VSUihob3N0LT5idXNfY2xrKSkKPiA+ICsgICAgICAgICAgICAgcmV0dXJuIGRldl9l cnJfcHJvYmUoJnBkZXYtPmRldiwgUFRSX0VSUihob3N0LT5idXNfY2xrKSwKPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgImZhaWxlZCB0byBnZXQgYnVzIGNsb2NrLlxuIik7 Cj4gPiArCj4gPiArICAgICBob3N0LT5kbWljX2NsayA9IGRldm1fY2xrX2dldCgmcGRldi0+ZGV2 LCAibW9kIik7Cj4gPiArICAgICBpZiAoSVNfRVJSKGhvc3QtPmRtaWNfY2xrKSkKPiA+ICsgICAg ICAgICAgICAgcmV0dXJuIGRldl9lcnJfcHJvYmUoJnBkZXYtPmRldiwgUFRSX0VSUihob3N0LT5k bWljX2NsayksCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmYWlsZWQg dG8gZ2V0IGRtaWMgY2xvY2suXG4iKTsKPiA+ICsKPiA+ICsgICAgIGhvc3QtPmRtYV9wYXJhbXNf cnguYWRkciA9IHJlcy0+c3RhcnQgKyBTVU41MElfRE1JQ19EQVRBOwo+ID4gKyAgICAgaG9zdC0+ ZG1hX3BhcmFtc19yeC5tYXhidXJzdCA9IDg7Cj4gPiArCj4gPiArICAgICBwbGF0Zm9ybV9zZXRf ZHJ2ZGF0YShwZGV2LCBob3N0KTsKPiA+ICsKPiA+ICsgICAgIGhvc3QtPnJzdCA9IGRldm1fcmVz ZXRfY29udHJvbF9nZXRfb3B0aW9uYWxfZXhjbHVzaXZlKCZwZGV2LT5kZXYsIE5VTEwpOwo+ID4g KyAgICAgaWYgKElTX0VSUihob3N0LT5yc3QpKQo+ID4gKyAgICAgICAgICAgICByZXR1cm4gZGV2 X2Vycl9wcm9iZSgmcGRldi0+ZGV2LCBQVFJfRVJSKGhvc3QtPnJzdCksCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICJGYWlsZWQgdG8gZ2V0IHJlc2V0LlxuIik7Cj4KPiBZ b3VyIGJpbmRpbmcgc3RhdGVzIHRoYXQgdGhlIHJlc2V0IGlzIG1hbmRhdG9yeSBzbyB5b3UgZG9u J3QgbmVlZCB0aGUKPiBvcHRpb25hbCB2YXJpYW50Lgo+Cj4gPiArICAgICByZXNldF9jb250cm9s X2RlYXNzZXJ0KGhvc3QtPnJzdCk7Cj4KPiBDYW4ndCB0aGlzIGJlIG1vdmVkIHRvIHRoZSBydW50 aW1lX3BtIGhvb2tzPwoKSXMgdGhpcyBuZWNlc3Nhcnk/IEkgc2VlIHRoYXQgbW9zdCBvZiB0aGUg ZHJpdmVyIGZpbGVzIGV4ZWN1dGUKcmVzZXRfY29udHJvbF9kZWFzc2VydCBpbiB0aGUgcHJvYmUg ZnVuY3Rpb24sIGFuZCByZXNldF9jb250cm9sX2Fzc2VydAppbiB0aGUgcmVtb3ZlIGZ1bmN0aW9u LgoKPgo+ID4gKyAgICAgcmV0ID0gZGV2bV9zbmRfc29jX3JlZ2lzdGVyX2NvbXBvbmVudCgmcGRl di0+ZGV2LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJnN1bjUwaV9kbWljX2Nv bXBvbmVudCwgJnN1bjUwaV9kbWljX2RhaSwgMSk7Cj4KPiBZb3VyIHNlY29uZCBsaW5lIHNob3Vs ZCBiZSBhbGlnbmVkIG9uIHRoZSBvcGVuaW5nIHBhcmVudGhlc2lzCj4KPiA+ICsgICAgIGlmIChy ZXQpCj4gPiArICAgICAgICAgICAgIHJldHVybiBkZXZfZXJyX3Byb2JlKCZwZGV2LT5kZXYsIHJl dCwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZhaWxlZCB0byByZWdp c3RlciBjb21wb25lbnQuXG4iKTsKPiA+ICsKPiA+ICsgICAgIHBtX3J1bnRpbWVfZW5hYmxlKCZw ZGV2LT5kZXYpOwo+ID4gKyAgICAgaWYgKCFwbV9ydW50aW1lX2VuYWJsZWQoJnBkZXYtPmRldikp IHsKPiA+ICsgICAgICAgICAgICAgcmV0ID0gc3VuNTBpX2RtaWNfcnVudGltZV9yZXN1bWUoJnBk ZXYtPmRldik7Cj4gPiArICAgICAgICAgICAgIGlmIChyZXQpCj4gPiArICAgICAgICAgICAgICAg ICAgICAgZ290byBlcnJfdW5yZWdpc3RlcjsKPiA+ICsgICAgIH0KPgo+IFdlIGhhdmUgYSBkZXBl bmRzIG9uIFBNIG9uIHNvbWUgZHJpdmVycyBhbHJlYWR5LCBzbyBJIGd1ZXNzIGl0IHdvdWxkCj4g anVzdCBtYWtlIHNlbnNlIHRvIGFkZCBvbmUgbW9yZSBoZXJlIGluc3RlYWQgb2YgZGVhbGluZyB3 aXRoIHdoZXRoZXIKPiBydW50aW1lX3BtIGlzIGNvbXBpbGVkIGluIG9yIG5vdC4KCkkgZG9uJ3Qg dW5kZXJzdGFuZC4gSSBhbSByZWZlcnJpbmcgdG8gdGhlIHN1bjRpLXNwZGlmLmMgZmlsZS4gV2hp Y2gKZHJpdmVyIGZpbGVzIHNob3VsZCBJIHJlZmVyIHRvPwoKPgo+IEFsc28sIHRoZSBuYW1lIG9m IHRoZSBsYWJlbCBpcyBtaXNsZWFkaW5nOiBpdCdzIGNhbGxlZCBlcnJfdW5yZWdpc3Rlcgo+IGJ1 dCB5b3UgZG9uJ3QgbmVlZCB0byB1bnJlZ2lzdGVyIGFueXRoaW5nIGFuZCB5b3UgYWN0dWFsbHkg ZGlzYWJsZQo+IHJ1bnRpbWVfcG0gZm9yIHRoYXQgZGV2aWNlLgo+Cj4gZXJyX2Rpc2FibGVfcnVu dGltZV9wbSBvciBzb21ldGhpbmcgc2ltaWxhciB3b3VsZCBiZSBhIGJldHRlciBwaWNrCj4KPiBU aGFua3MhCj4gTWF4aW1lCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxp c3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1hcm0ta2VybmVsCg==