From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dmitry Osipenko Subject: Re: [alsa-devel] [PATCH 4/9] ASoC: tegra: add Tegra210 based I2S driver Date: Tue, 21 Jan 2020 08:15:47 +0300 Message-ID: References: <1579530198-13431-1-git-send-email-spujar@nvidia.com> <1579530198-13431-5-git-send-email-spujar@nvidia.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Return-path: In-Reply-To: <1579530198-13431-5-git-send-email-spujar@nvidia.com> Content-Language: en-US Sender: linux-kernel-owner@vger.kernel.org To: Sameer Pujar , perex@perex.cz, tiwai@suse.com, robh+dt@kernel.org Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, atalambedu@nvidia.com, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, jonathanh@nvidia.com, viswanathl@nvidia.com, sharadg@nvidia.com, broonie@kernel.org, thierry.reding@gmail.com, linux-tegra@vger.kernel.org, rlokhande@nvidia.com, mkumard@nvidia.com, dramesh@nvidia.com List-Id: linux-tegra@vger.kernel.org 20.01.2020 17:23, Sameer Pujar пишет: > The Inter-IC Sound (I2S) controller implements full-duplex, bi-directional > and single direction point to point serial interface. It can interface > with I2S compatible devices. Tegra I2S controller can operate as both > master and slave. > > This patch registers I2S controller with ASoC framework. The component > driver exposes DAPM widgets, routes and kcontrols for the device. The DAI > driver exposes I2S interfaces, which can be used to connect different > components in the ASoC layer. Makefile and Kconfig support is added to > allow to build the driver. The I2S devices can be enabled in the DT via > "nvidia,tegra210-i2s" compatible binding. > > Signed-off-by: Sameer Pujar > --- > sound/soc/tegra/Kconfig | 10 + > sound/soc/tegra/Makefile | 2 + > sound/soc/tegra/tegra210_i2s.c | 941 +++++++++++++++++++++++++++++++++++++++++ > sound/soc/tegra/tegra210_i2s.h | 132 ++++++ > 4 files changed, 1085 insertions(+) > create mode 100644 sound/soc/tegra/tegra210_i2s.c > create mode 100644 sound/soc/tegra/tegra210_i2s.h > > diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig > index 2bde1e6..157fa7a 100644 > --- a/sound/soc/tegra/Kconfig > +++ b/sound/soc/tegra/Kconfig > @@ -73,6 +73,16 @@ config SND_SOC_TEGRA210_DMIC > PDM receiver. > Say Y or M if you want to add support for Tegra210 DMIC module. > > +config SND_SOC_TEGRA210_I2S > + tristate "Tegra210 I2S module" > + depends on SND_SOC_TEGRA > + help > + Config to enable the Inter-IC Sound (I2S) Controller which > + implements full-duplex and bidirectional and single direction > + point-to-point serial interfaces. It can interface with I2S > + compatible devices. > + Say Y or M if you want to add support for Tegra210 I2S module. > + > config SND_SOC_TEGRA_RT5640 > tristate "SoC Audio support for Tegra boards using an RT5640 codec" > depends on SND_SOC_TEGRA && I2C && GPIOLIB > diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile > index 9e78fe4..1c4457d 100644 > --- a/sound/soc/tegra/Makefile > +++ b/sound/soc/tegra/Makefile > @@ -10,6 +10,7 @@ snd-soc-tegra30-ahub-objs := tegra30_ahub.o > snd-soc-tegra30-i2s-objs := tegra30_i2s.o > snd-soc-tegra-cif-objs := tegra_cif.o > snd-soc-tegra210-dmic-objs := tegra210_dmic.o > +snd-soc-tegra210-i2s-objs := tegra210_i2s.o > > obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o > obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o > @@ -21,6 +22,7 @@ obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o > obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o > obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o > obj-$(CONFIG_SND_SOC_TEGRA210_DMIC) += snd-soc-tegra210-dmic.o > +obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o > > # Tegra machine Support > snd-soc-tegra-rt5640-objs := tegra_rt5640.o > diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c > new file mode 100644 > index 0000000..36e8a7c > --- /dev/null > +++ b/sound/soc/tegra/tegra210_i2s.c > @@ -0,0 +1,941 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * tegra210_i2s.c - Tegra210 I2S driver > + * > + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "tegra210_i2s.h" > +#include "tegra_cif.h" Headers should be sorted in alphabet order to avoid confusion about how to insert a new header. > +#define DRV_NAME "tegra210-i2s" > + > +static const struct reg_default tegra210_i2s_reg_defaults[] = { > + { TEGRA210_I2S_RX_INT_MASK, 0x00000003}, > + { TEGRA210_I2S_RX_CIF_CTRL, 0x00007700}, > + { TEGRA210_I2S_TX_INT_MASK, 0x00000003}, > + { TEGRA210_I2S_TX_CIF_CTRL, 0x00007700}, > + { TEGRA210_I2S_CG, 0x1}, > + { TEGRA210_I2S_TIMING, 0x0000001f}, > + { TEGRA210_I2S_ENABLE, 0x1}, > + /* > + * Below update does not have any effect on Tegra186 and Tegra194. > + * On Tegra210, I2S4 has "i2s4a" and "i2s4b" pins and below update > + * is required to select i2s4b for it to be functional for I2S > + * operation. > + */ > + { TEGRA210_I2S_CYA, 0x1}, > +}; > + > +static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap, > + unsigned int total_slots, > + unsigned int tx_slot_mask, > + unsigned int rx_slot_mask) > +{ > + regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1); > + regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask); > + regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask); > +} > + > +static int tegra210_i2s_set_clock_rate(struct device *dev, > + unsigned int clock_rate) > +{ > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + unsigned int val; > + int ret; > + > + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); > + > + /* No need to set rates if I2S is being operated in slave */ > + if (!(val & I2S_CTRL_MASTER_EN)) > + return 0; > + > + ret = clk_set_rate(i2s->clk_i2s, clock_rate); > + if (ret) { > + dev_err(dev, "failed to set I2S bit clock rate %u, err: %d\n", > + clock_rate, ret); > + return ret; > + } > + > + if (!IS_ERR(i2s->clk_sync_input)) { > + /* > + * Other I/O modules in AHUB can use i2s bclk as reference > + * clock. Below sets sync input clock rate as per bclk, > + * which can be used as input to other I/O modules. > + */ > + ret = clk_set_rate(i2s->clk_sync_input, clock_rate); > + if (ret) { > + dev_err(dev, > + "failed to set sync input rate %u, err = %d\n", > + clock_rate, ret); > + return ret; > + } > + } > + > + return 0; > +} > + > +static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, > + bool is_playback) > +{ > + struct device *dev = compnt->dev; > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + unsigned int reset_mask = I2S_SOFT_RESET_MASK; > + unsigned int reset_en = I2S_SOFT_RESET_EN; > + unsigned int reset_reg, cif_reg, stream_reg; > + unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val; > + int ret; > + > + if (is_playback) { > + reset_reg = TEGRA210_I2S_RX_SOFT_RESET; > + cif_reg = TEGRA210_I2S_RX_CIF_CTRL; > + stream_reg = TEGRA210_I2S_RX_CTRL; > + } else { > + reset_reg = TEGRA210_I2S_TX_SOFT_RESET; > + cif_reg = TEGRA210_I2S_TX_CIF_CTRL; > + stream_reg = TEGRA210_I2S_TX_CTRL; > + } > + > + /* Store */ > + regmap_read(i2s->regmap, cif_reg, &cif_ctrl); > + regmap_read(i2s->regmap, stream_reg, &stream_ctrl); > + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl); > + > + /* Reset */ > + regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en); > + > + ret = regmap_read_poll_timeout(i2s->regmap, reset_reg, val, > + !(val & reset_mask & reset_en), > + 10, 10000); > + if (ret < 0) { > + dev_err(dev, "timeout: failed to reset I2S for %s\n", > + is_playback ? "playback" : "capture"); > + return ret; > + } > + > + /* Restore */ > + regmap_write(i2s->regmap, cif_reg, cif_ctrl); > + regmap_write(i2s->regmap, stream_reg, stream_ctrl); > + regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl); > + > + return 0; > +} > + > +static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, > + struct snd_kcontrol *kcontrol, int event) > +{ > + struct snd_soc_component *compnt = snd_soc_dapm_to_component(w->dapm); > + struct device *dev = compnt->dev; > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + unsigned int val, status_reg; > + bool is_playback; > + int ret; > + > + switch (w->reg) { > + case TEGRA210_I2S_RX_ENABLE: > + is_playback = true; > + status_reg = TEGRA210_I2S_RX_STATUS; > + break; > + case TEGRA210_I2S_TX_ENABLE: > + is_playback = false; > + status_reg = TEGRA210_I2S_TX_STATUS; > + break; > + default: > + return -EINVAL; > + } > + > + /* Ensure I2S is in disabled state before new session */ > + ret = regmap_read_poll_timeout(i2s->regmap, status_reg, val, > + !(val & I2S_EN_MASK & I2S_EN), > + 10, 10000); > + if (ret < 0) { > + dev_err(dev, "timeout: previous I2S %s is still active\n", > + is_playback ? "playback" : "capture"); > + return ret; > + } > + > + /* SW reset */ Comments should amend code with useful information. > + return tegra210_i2s_sw_reset(compnt, is_playback); > +} > + > +static int tegra210_i2s_runtime_suspend(struct device *dev) > +{ > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + > + regcache_cache_only(i2s->regmap, true); > + regcache_mark_dirty(i2s->regmap); > + > + clk_disable_unprepare(i2s->clk_i2s); > + > + return 0; > +} > + > +static int tegra210_i2s_runtime_resume(struct device *dev) > +{ > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + int ret; > + > + ret = clk_prepare_enable(i2s->clk_i2s); > + if (ret) { > + dev_err(dev, "failed to enable I2S bit clock, err: %d\n", ret); > + return ret; > + } > + > + regcache_cache_only(i2s->regmap, false); > + regcache_sync(i2s->regmap); > + > + return 0; > +} > + > +static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s, > + unsigned int data_offset) > +{ > + unsigned int mask = I2S_CTRL_DATA_OFFSET_MASK; > + unsigned int shift = I2S_DATA_SHIFT; > + unsigned int reg; > + > + reg = TEGRA210_I2S_TX_CTRL; > + regmap_update_bits(i2s->regmap, reg, mask, data_offset << shift); > + > + reg = TEGRA210_I2S_RX_CTRL; > + regmap_update_bits(i2s->regmap, reg, mask, data_offset << shift); > +} > + > +static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, > + unsigned int fmt) > +{ > + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); > + unsigned int mask, val; > + > + mask = I2S_CTRL_MASTER_EN_MASK; > + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { > + case SND_SOC_DAIFMT_CBS_CFS: > + val = 0; > + break; > + case SND_SOC_DAIFMT_CBM_CFM: > + val = I2S_CTRL_MASTER_EN; > + break; > + default: > + return -EINVAL; > + } > + > + mask |= I2S_CTRL_FRAME_FMT_MASK | I2S_CTRL_LRCK_POL_MASK; > + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { > + case SND_SOC_DAIFMT_DSP_A: > + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; > + val |= I2S_CTRL_LRCK_POL_HIGH; > + tegra210_i2s_set_data_offset(i2s, 1); > + break; > + case SND_SOC_DAIFMT_DSP_B: > + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; > + val |= I2S_CTRL_LRCK_POL_HIGH; > + tegra210_i2s_set_data_offset(i2s, 0); > + break; > + /* I2S mode has data offset of 1 */ > + case SND_SOC_DAIFMT_I2S: > + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; > + val |= I2S_CTRL_LRCK_POL_LOW; > + tegra210_i2s_set_data_offset(i2s, 1); > + break; > + /* > + * For RJ mode data offset is dependent on the sample size > + * and the bclk ratio, and so is set when hw_params is called. > + */ > + case SND_SOC_DAIFMT_RIGHT_J: > + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; > + val |= I2S_CTRL_LRCK_POL_HIGH; > + break; > + case SND_SOC_DAIFMT_LEFT_J: > + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; > + val |= I2S_CTRL_LRCK_POL_HIGH; > + tegra210_i2s_set_data_offset(i2s, 0); > + break; > + default: > + return -EINVAL; > + } > + > + mask |= I2S_CTRL_EDGE_CTRL_MASK; > + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { > + case SND_SOC_DAIFMT_NB_NF: > + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; > + break; > + case SND_SOC_DAIFMT_NB_IF: > + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; > + val ^= I2S_CTRL_LRCK_POL_MASK; > + break; > + case SND_SOC_DAIFMT_IB_NF: > + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; > + break; > + case SND_SOC_DAIFMT_IB_IF: > + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; > + val ^= I2S_CTRL_LRCK_POL_MASK; > + break; > + default: > + return -EINVAL; > + } > + > + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val); > + > + i2s->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; > + > + return 0; > +} > + > +static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, > + unsigned int tx_mask, unsigned int rx_mask, > + int slots, int slot_width) > +{ > + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); > + > + /* Copy the required tx and rx mask */ > + i2s->tx_mask = (tx_mask > DEFAULT_I2S_SLOT_MASK) ? > + DEFAULT_I2S_SLOT_MASK : tx_mask; > + i2s->rx_mask = (rx_mask > DEFAULT_I2S_SLOT_MASK) ? > + DEFAULT_I2S_SLOT_MASK : rx_mask; > + > + return 0; > +} > + > +static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, > + unsigned int ratio) > +{ > + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); > + > + i2s->bclk_ratio = ratio; > + > + return 0; > +} > + > +static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); > + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); > + long *uctl_val = &ucontrol->value.integer.value[0]; > + > + if (strstr(kcontrol->id.name, "Loopback")) > + *uctl_val = i2s->loopback; > + else if (strstr(kcontrol->id.name, "Sample Rate")) > + *uctl_val = i2s->srate_override; > + else if (strstr(kcontrol->id.name, "FSYNC Width")) > + *uctl_val = i2s->fsync_width; > + else if (strstr(kcontrol->id.name, "Playback Audio Bit Format")) > + *uctl_val = i2s->audio_fmt_override[I2S_RX_PATH]; > + else if (strstr(kcontrol->id.name, "Capture Audio Bit Format")) > + *uctl_val = i2s->audio_fmt_override[I2S_TX_PATH]; > + else if (strstr(kcontrol->id.name, "Client Bit Format")) > + *uctl_val = i2s->client_fmt_override; > + else if (strstr(kcontrol->id.name, "Playback Audio Channels")) > + *uctl_val = i2s->audio_ch_override[I2S_RX_PATH]; > + else if (strstr(kcontrol->id.name, "Capture Audio Channels")) > + *uctl_val = i2s->audio_ch_override[I2S_TX_PATH]; > + else if (strstr(kcontrol->id.name, "Client Channels")) > + *uctl_val = i2s->client_ch_override; > + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) > + *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; > + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) > + *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; > + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) > + *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; > + else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) > + *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; > + else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) > + *uctl_val = i2s->rx_fifo_th; > + else if (strstr(kcontrol->id.name, "BCLK Ratio")) > + *uctl_val = i2s->bclk_ratio; > + > + return 0; > +} > + > +static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) Checkpatch should complain about the wrong indentation here. > +{ > + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); > + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); > + int value = ucontrol->value.integer.value[0]; > + > + if (strstr(kcontrol->id.name, "Loopback")) { > + i2s->loopback = value; > + > + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, > + I2S_CTRL_LPBK_MASK, > + i2s->loopback << I2S_CTRL_LPBK_SHIFT); > + > + } else if (strstr(kcontrol->id.name, "Sample Rate")) > + i2s->srate_override = value; > + else if (strstr(kcontrol->id.name, "FSYNC Width")) { > + /* > + * Frame sync width is used only for FSYNC modes and not > + * applicable for LRCK modes. Reset value for this field is "0", > + * which means the width is one bit clock wide. > + * The width requirement may depend on the codec and in such > + * cases mixer control is used to update custom values. A value > + * of "N" here means, width is "N + 1" bit clock wide. > + */ > + i2s->fsync_width = value; > + > + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, > + I2S_CTRL_FSYNC_WIDTH_MASK, > + i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); > + > + } else if (strstr(kcontrol->id.name, "Playback Audio Bit Format")) > + i2s->audio_fmt_override[I2S_RX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Capture Audio Bit Format")) > + i2s->audio_fmt_override[I2S_TX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Client Bit Format")) > + i2s->client_fmt_override = value; > + else if (strstr(kcontrol->id.name, "Playback Audio Channels")) > + i2s->audio_ch_override[I2S_RX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Capture Audio Channels")) > + i2s->audio_ch_override[I2S_TX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Client Channels")) > + i2s->client_ch_override = value; > + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) > + i2s->stereo_to_mono[I2S_TX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) > + i2s->mono_to_stereo[I2S_TX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) > + i2s->stereo_to_mono[I2S_RX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) > + i2s->mono_to_stereo[I2S_RX_PATH] = value; > + else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) > + i2s->rx_fifo_th = value; > + else if (strstr(kcontrol->id.name, "BCLK Ratio")) > + i2s->bclk_ratio = value; I'm pretty sure that checkpatch should complain about the missing brackets, they should make code's indentation uniform and thus easier to read. Same for all other occurrences in the code. > + return 0; > +} > + > +static const char * const tegra210_i2s_format_text[] = { > + "None", > + "16", > + "32", > +}; > + > +static const int tegra210_cif_fmt[] = { > + 0, > + TEGRA_ACIF_BITS_16, > + TEGRA_ACIF_BITS_32, > +}; > + > +static const int tegra210_i2s_bit_fmt[] = { > + 0, > + I2S_BITS_16, > + I2S_BITS_32, > +}; > + > +static const int tegra210_i2s_sample_size[] = { > + 0, > + 16, > + 32, > +}; > + > +static const struct soc_enum tegra210_i2s_format_enum = > + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_format_text), > + tegra210_i2s_format_text); > + > +static int tegra210_i2s_set_timing_params(struct device *dev, > + unsigned int sample_size, > + unsigned int srate, > + unsigned int channels) > +{ > + struct tegra210_i2s *i2s = dev_get_drvdata(dev); > + unsigned int val, bit_count, bclk_rate, num_bclk = sample_size; > + int ret; > + > + if (i2s->bclk_ratio) > + num_bclk *= i2s->bclk_ratio; > + > + if (i2s->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) > + tegra210_i2s_set_data_offset(i2s, num_bclk - sample_size); > + > + /* I2S bit clock rate */ > + bclk_rate = srate * channels * num_bclk; > + > + ret = tegra210_i2s_set_clock_rate(dev, bclk_rate); > + if (ret) { > + dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n", > + bclk_rate, ret); > + return ret; > + } > + > + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); > + > + /* > + * For LRCK mode, channel bit count depends on number of bit clocks > + * on the left channel, where as for FSYNC mode bit count depends on > + * the number of bit clocks in both left and right channels for DSP > + * mode or the number of bit clocks in one TDM frame. > + * > + */ > + switch (val & I2S_CTRL_FRAME_FMT_MASK) { > + case I2S_CTRL_FRAME_FMT_LRCK_MODE: > + bit_count = (bclk_rate / (srate * 2)) - 1; > + break; > + case I2S_CTRL_FRAME_FMT_FSYNC_MODE: > + bit_count = (bclk_rate / srate) - 1; > + > + tegra210_i2s_set_slot_ctrl(i2s->regmap, channels, > + i2s->tx_mask, i2s->rx_mask); > + break; > + default: > + dev_err(dev, "invalid I2S mode\n"); > + return -EINVAL; > + } > + > + if (bit_count > I2S_TIMING_CH_BIT_CNT_MASK) { > + dev_err(dev, "invalid channel bit count %u\n", bit_count); > + return -EINVAL; > + } > + > + regmap_write(i2s->regmap, TEGRA210_I2S_TIMING, > + bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT); > + > + return 0; > +} > + > +static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct snd_soc_dai *dai) > +{ > + struct device *dev = dai->dev; > + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); > + unsigned int sample_size, channels, srate, val, reg, path; > + struct tegra_cif_conf cif_conf; > + int max_th; > + > + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); > + > + channels = params_channels(params); > + if (channels < 1) { > + dev_err(dev, "invalid %d channel configuration\n", channels); > + return -EINVAL; > + } > + > + cif_conf.audio_ch = channels; > + cif_conf.client_ch = channels; > + > + switch (params_format(params)) { > + case SNDRV_PCM_FORMAT_S8: > + val = I2S_BITS_8; > + sample_size = 8; > + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; > + cif_conf.client_bits = TEGRA_ACIF_BITS_8; > + break; > + case SNDRV_PCM_FORMAT_S16_LE: > + val = I2S_BITS_16; > + sample_size = 16; > + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; > + cif_conf.client_bits = TEGRA_ACIF_BITS_16; > + break; > + case SNDRV_PCM_FORMAT_S32_LE: > + val = I2S_BITS_32; > + sample_size = 32; > + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; > + cif_conf.client_bits = TEGRA_ACIF_BITS_32; > + break; > + default: > + dev_err(dev, "unsupported format!\n"); > + return -ENOTSUPP; > + } > + > + if (i2s->client_fmt_override) { > + val = tegra210_i2s_bit_fmt[i2s->client_fmt_override]; > + sample_size = > + tegra210_i2s_sample_size[i2s->client_fmt_override]; > + cif_conf.client_bits = > + tegra210_cif_fmt[i2s->client_fmt_override]; > + } > + > + /* Program sample size */ > + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, > + I2S_CTRL_BIT_SIZE_MASK, val); > + > + srate = params_rate(params); > + > + /* Override rate, channel and audio bit params as applicable */ > + if (i2s->srate_override) > + srate = i2s->srate_override; > + > + /* > + * For playback I2S RX-CIF and for capture TX-CIF is used. > + * With reference to AHUB, for I2S, SNDRV_PCM_STREAM_CAPTURE stream is > + * actually for playback. > + */ > + path = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ? > + I2S_RX_PATH : I2S_TX_PATH; > + > + if (i2s->audio_ch_override[path]) > + cif_conf.audio_ch = i2s->audio_ch_override[path]; > + > + if (i2s->client_ch_override) > + cif_conf.client_ch = i2s->client_ch_override; > + > + if (i2s->audio_fmt_override[path]) > + cif_conf.audio_bits = > + tegra210_cif_fmt[i2s->audio_fmt_override[path]]; > + > + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { > + reg = TEGRA210_I2S_RX_CIF_CTRL; > + > + /* FIFO threshold in terms of frames */ > + max_th = (I2S_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; > + if (max_th < 0) > + return -EINVAL; > + > + if (i2s->rx_fifo_th > max_th) > + i2s->rx_fifo_th = max_th; > + > + cif_conf.threshold = i2s->rx_fifo_th; > + } else > + reg = TEGRA210_I2S_TX_CIF_CTRL; > + > + cif_conf.mono_conv = i2s->mono_to_stereo[path]; > + cif_conf.stereo_conv = i2s->stereo_to_mono[path]; > + > + tegra_set_cif(i2s->regmap, reg, &cif_conf); > + > + return tegra210_i2s_set_timing_params(dev, sample_size, srate, > + cif_conf.client_ch); > +} > + > +static struct snd_soc_dai_ops tegra210_i2s_dai_ops = { const? > + .set_fmt = tegra210_i2s_set_fmt, > + .hw_params = tegra210_i2s_hw_params, > + .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, > + .set_tdm_slot = tegra210_i2s_set_tdm_slot, > +}; > + > +/* > + * Three DAIs are exposed > + * 1. "CIF" DAI for connecting with XBAR > + * 2. "DAP" DAI for connecting with CODEC > + * 3. "DUMMY" can be used when no external codec connection is > + * available. In such case "DAP" is connected with "DUMMY". > + * Order of these DAIs should not be changed, since DAI links in DT refer > + * to these DAIs depending on the index. > + */ > +static struct snd_soc_dai_driver tegra210_i2s_dais[] = { > + { > + .name = "CIF", > + .playback = { > + .stream_name = "CIF Receive", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + .capture = { > + .stream_name = "CIF Transmit", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + }, > + { > + .name = "DAP", > + .playback = { > + .stream_name = "DAP Receive", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + .capture = { > + .stream_name = "DAP Transmit", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + .ops = &tegra210_i2s_dai_ops, > + .symmetric_rates = 1, > + }, > + { > + .name = "DUMMY", > + .playback = { > + .stream_name = "Dummy Playback", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + .capture = { > + .stream_name = "Dummy Capture", > + .channels_min = 1, > + .channels_max = 16, > + .rates = SNDRV_PCM_RATE_8000_192000, > + .formats = SNDRV_PCM_FMTBIT_S8 | > + SNDRV_PCM_FMTBIT_S16_LE | > + SNDRV_PCM_FMTBIT_S32_LE, > + }, > + }, > +}; > + > +static const char * const tegra210_i2s_stereo_conv_text[] = { > + "CH0", "CH1", "AVG", > +}; > + > +static const char * const tegra210_i2s_mono_conv_text[] = { > + "ZERO", "COPY", > +}; > + > +static const struct soc_enum tegra210_i2s_mono_conv_enum = > + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_mono_conv_text), > + tegra210_i2s_mono_conv_text); > + > +static const struct soc_enum tegra210_i2s_stereo_conv_enum = > + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_stereo_conv_text), > + tegra210_i2s_stereo_conv_text); > + > +static const struct snd_kcontrol_new tegra210_i2s_controls[] = { > + SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, > + tegra210_i2s_put_control), > + SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, > + tegra210_i2s_put_control), > + SOC_SINGLE_EXT("Sample Rate", 0, 0, 192000, 0, tegra210_i2s_get_control, > + tegra210_i2s_put_control), > + SOC_ENUM_EXT("Playback Audio Bit Format", tegra210_i2s_format_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Capture Audio Bit Format", tegra210_i2s_format_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Client Bit Format", tegra210_i2s_format_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_SINGLE_EXT("Playback Audio Channels", 0, 0, 16, 0, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_SINGLE_EXT("Capture Audio Channels", 0, 0, 16, 0, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_SINGLE_EXT("Client Channels", 0, 0, 16, 0, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, > + tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, > + 0, tegra210_i2s_get_control, tegra210_i2s_put_control), > + SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, > + tegra210_i2s_put_control), > +}; > + > +static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { > + SND_SOC_DAPM_AIF_IN("CIF RX", NULL, 0, SND_SOC_NOPM, 0, 0), > + SND_SOC_DAPM_AIF_OUT("CIF TX", NULL, 0, SND_SOC_NOPM, 0, 0), > + SND_SOC_DAPM_AIF_IN_E("DAP RX", NULL, 0, TEGRA210_I2S_TX_ENABLE, > + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), > + SND_SOC_DAPM_AIF_OUT_E("DAP TX", NULL, 0, TEGRA210_I2S_RX_ENABLE, > + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), > + SND_SOC_DAPM_MIC("Dummy Input", NULL), > + SND_SOC_DAPM_SPK("Dummy Output", NULL), > +}; > + > +static const struct snd_soc_dapm_route tegra210_i2s_routes[] = { > + { "CIF RX", NULL, "CIF Receive" }, > + { "DAP TX", NULL, "CIF RX" }, > + { "DAP Transmit", NULL, "DAP TX" }, > + > + { "DAP RX", NULL, "DAP Receive" }, > + { "CIF TX", NULL, "DAP RX" }, > + { "CIF Transmit", NULL, "CIF TX" }, > + > + { "Dummy Capture", NULL, "Dummy Input" }, > + { "Dummy Output", NULL, "Dummy Playback" }, > +}; > + > +static const struct snd_soc_component_driver tegra210_i2s_cmpnt = { > + .dapm_widgets = tegra210_i2s_widgets, > + .num_dapm_widgets = ARRAY_SIZE(tegra210_i2s_widgets), > + .dapm_routes = tegra210_i2s_routes, > + .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes), > + .controls = tegra210_i2s_controls, > + .num_controls = ARRAY_SIZE(tegra210_i2s_controls), > + .non_legacy_dai_naming = 1, > +}; > + > +static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET: > + case TEGRA210_I2S_RX_INT_MASK ... TEGRA210_I2S_RX_CLK_TRIM: > + case TEGRA210_I2S_TX_ENABLE ... TEGRA210_I2S_TX_SOFT_RESET: > + case TEGRA210_I2S_TX_INT_MASK ... TEGRA210_I2S_TX_CLK_TRIM: > + case TEGRA210_I2S_ENABLE ... TEGRA210_I2S_CG: > + case TEGRA210_I2S_CTRL ... TEGRA210_I2S_CYA: > + return true; > + default: > + return false; > + }; > +} > + > +static bool tegra210_i2s_rd_reg(struct device *dev, unsigned int reg) > +{ > + if (tegra210_i2s_wr_reg(dev, reg)) > + return true; > + > + switch (reg) { > + case TEGRA210_I2S_RX_STATUS: > + case TEGRA210_I2S_RX_INT_STATUS: > + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: > + case TEGRA210_I2S_TX_STATUS: > + case TEGRA210_I2S_TX_INT_STATUS: > + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: > + case TEGRA210_I2S_STATUS: > + case TEGRA210_I2S_INT_STATUS: > + return true; > + default: > + return false; > + }; > +} > + > +static bool tegra210_i2s_volatile_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case TEGRA210_I2S_RX_STATUS: > + case TEGRA210_I2S_RX_INT_STATUS: > + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: > + case TEGRA210_I2S_TX_STATUS: > + case TEGRA210_I2S_TX_INT_STATUS: > + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: > + case TEGRA210_I2S_STATUS: > + case TEGRA210_I2S_INT_STATUS: > + case TEGRA210_I2S_RX_SOFT_RESET: > + case TEGRA210_I2S_TX_SOFT_RESET: > + return true; > + default: > + return false; > + }; > +} > + > +static const struct regmap_config tegra210_i2s_regmap_config = { > + .reg_bits = 32, > + .reg_stride = 4, > + .val_bits = 32, > + .max_register = TEGRA210_I2S_CYA, > + .writeable_reg = tegra210_i2s_wr_reg, > + .readable_reg = tegra210_i2s_rd_reg, > + .volatile_reg = tegra210_i2s_volatile_reg, > + .reg_defaults = tegra210_i2s_reg_defaults, > + .num_reg_defaults = ARRAY_SIZE(tegra210_i2s_reg_defaults), > + .cache_type = REGCACHE_FLAT, > +}; > + > +static const struct of_device_id tegra210_i2s_of_match[] = { > + { .compatible = "nvidia,tegra210-i2s" }, > + {}, > +}; > + > +static int tegra210_i2s_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct tegra210_i2s *i2s; > + void __iomem *regs; > + int ret = 0; Please do not initialize variables if it's not really needed, to keep code cleaner. Same for all other occurrences in the code. > + i2s = devm_kcalloc(dev, 1, sizeof(*i2s), GFP_KERNEL); > + if (!i2s) > + return -ENOMEM; > + > + i2s->rx_fifo_th = DEFAULT_I2S_RX_FIFO_THRESHOLD; > + i2s->tx_mask = i2s->rx_mask = DEFAULT_I2S_SLOT_MASK; > + i2s->loopback = false; > + > + dev_set_drvdata(dev, i2s); > + > + i2s->clk_i2s = devm_clk_get(dev, "i2s"); > + if (IS_ERR(i2s->clk_i2s)) { > + dev_err(dev, "can't retrieve I2S bit clock\n"); > + return PTR_ERR(i2s->clk_i2s); > + } > + > + /* > + * Not an error, as this clock is needed only when some other I/O > + * requires input clock from current I2S instance, which is > + * configurable from DT. > + */ > + i2s->clk_sync_input = devm_clk_get(dev, "sync_input"); > + if (IS_ERR(i2s->clk_sync_input)) > + dev_dbg(dev, "can't retrieve I2S sync input clock\n"); > + > + regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + > + i2s->regmap = devm_regmap_init_mmio(dev, regs, > + &tegra210_i2s_regmap_config); > + if (IS_ERR(i2s->regmap)) { > + dev_err(dev, "regmap init failed\n"); > + return PTR_ERR(i2s->regmap); > + } > + > + regcache_cache_only(i2s->regmap, true); > + > + ret = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt, > + tegra210_i2s_dais, > + ARRAY_SIZE(tegra210_i2s_dais)); > + if (ret != 0) { > + dev_err(dev, "can't register I2S component, err: %d\n", ret); > + return ret; > + } > + > + pm_runtime_enable(dev); Error checking? > + return 0; > +} > + > +static int tegra210_i2s_remove(struct platform_device *pdev) > +{ > + pm_runtime_disable(&pdev->dev); > + if (!pm_runtime_status_suspended(&pdev->dev)) > + tegra210_i2s_runtime_suspend(&pdev->dev); This breaks device's RPM refcounting if it was disabled in the active state. This code should be removed. At most you could warn about the unxpected RPM state here, but it shouldn't be necessary. > + return 0; > +} > + > +static const struct dev_pm_ops tegra210_i2s_pm_ops = { > + SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, > + tegra210_i2s_runtime_resume, NULL) > + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, > + pm_runtime_force_resume) > +}; > + > +static struct platform_driver tegra210_i2s_driver = { > + .driver = { > + .name = DRV_NAME, Will be nicer to set the name directly here, thus to remove the DRV_NAME macro. > + .owner = THIS_MODULE, No need to explicitly set the owner, drivers core takes care about it. > + .of_match_table = tegra210_i2s_of_match, > + .pm = &tegra210_i2s_pm_ops, > + }, > + .probe = tegra210_i2s_probe, > + .remove = tegra210_i2s_remove, > +}; > +module_platform_driver(tegra210_i2s_driver) > + > +MODULE_AUTHOR("Songhee Baek "); > +MODULE_DESCRIPTION("Tegra210 ASoC I2S driver"); > +MODULE_LICENSE("GPL v2"); > +MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match); What about to place MODULE_DEVICE_TABLE() right after the definition of tegra210_i2s_of_match like it's done by most of the drivers in kernel? > diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h > new file mode 100644 > index 0000000..121dff7 > --- /dev/null > +++ b/sound/soc/tegra/tegra210_i2s.h > @@ -0,0 +1,132 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * tegra210_i2s.h - Definitions for Tegra210 I2S driver > + * > + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. > + * > + */ > + > +#ifndef __TEGRA210_I2S_H__ > +#define __TEGRA210_I2S_H__ > + > +/* Register offsets from I2S*_BASE */ > +#define TEGRA210_I2S_RX_ENABLE 0x0 > +#define TEGRA210_I2S_RX_SOFT_RESET 0x4 > +#define TEGRA210_I2S_RX_STATUS 0x0c > +#define TEGRA210_I2S_RX_INT_STATUS 0x10 > +#define TEGRA210_I2S_RX_INT_MASK 0x14 > +#define TEGRA210_I2S_RX_INT_SET 0x18 > +#define TEGRA210_I2S_RX_INT_CLEAR 0x1c > +#define TEGRA210_I2S_RX_CIF_CTRL 0x20 > +#define TEGRA210_I2S_RX_CTRL 0x24 > +#define TEGRA210_I2S_RX_SLOT_CTRL 0x28 > +#define TEGRA210_I2S_RX_CLK_TRIM 0x2c > +#define TEGRA210_I2S_RX_CYA 0x30 > +#define TEGRA210_I2S_RX_CIF_FIFO_STATUS 0x34 > +#define TEGRA210_I2S_TX_ENABLE 0x40 > +#define TEGRA210_I2S_TX_SOFT_RESET 0x44 > +#define TEGRA210_I2S_TX_STATUS 0x4c > +#define TEGRA210_I2S_TX_INT_STATUS 0x50 > +#define TEGRA210_I2S_TX_INT_MASK 0x54 > +#define TEGRA210_I2S_TX_INT_SET 0x58 > +#define TEGRA210_I2S_TX_INT_CLEAR 0x5c > +#define TEGRA210_I2S_TX_CIF_CTRL 0x60 > +#define TEGRA210_I2S_TX_CTRL 0x64 > +#define TEGRA210_I2S_TX_SLOT_CTRL 0x68 > +#define TEGRA210_I2S_TX_CLK_TRIM 0x6c > +#define TEGRA210_I2S_TX_CYA 0x70 > +#define TEGRA210_I2S_TX_CIF_FIFO_STATUS 0x74 > +#define TEGRA210_I2S_ENABLE 0x80 > +#define TEGRA210_I2S_SOFT_RESET 0x84 > +#define TEGRA210_I2S_CG 0x88 > +#define TEGRA210_I2S_STATUS 0x8c > +#define TEGRA210_I2S_INT_STATUS 0x90 > +#define TEGRA210_I2S_CTRL 0xa0 > +#define TEGRA210_I2S_TIMING 0xa4 > +#define TEGRA210_I2S_SLOT_CTRL 0xa8 > +#define TEGRA210_I2S_CLK_TRIM 0xac > +#define TEGRA210_I2S_CYA 0xb0 > + > +/* Bit fields, shifts and masks */ > +#define I2S_DATA_SHIFT 8 > +#define I2S_CTRL_DATA_OFFSET_MASK (0x7ff << I2S_DATA_SHIFT) > + > +#define I2S_EN_SHIFT 0 > +#define I2S_EN_MASK (1 << I2S_EN_SHIFT) > +#define I2S_EN (1 << I2S_EN_SHIFT) > + > +#define I2S_FSYNC_WIDTH_SHIFT 24 > +#define I2S_CTRL_FSYNC_WIDTH_MASK (0xff << I2S_FSYNC_WIDTH_SHIFT) > + > +#define I2S_POS_EDGE 0 > +#define I2S_NEG_EDGE 1 > +#define I2S_EDGE_SHIFT 20 > +#define I2S_CTRL_EDGE_CTRL_MASK (1 << I2S_EDGE_SHIFT) > +#define I2S_CTRL_EDGE_CTRL_POS_EDGE (I2S_POS_EDGE << I2S_EDGE_SHIFT) > +#define I2S_CTRL_EDGE_CTRL_NEG_EDGE (I2S_NEG_EDGE << I2S_EDGE_SHIFT) > + > +#define I2S_FMT_LRCK 0 > +#define I2S_FMT_FSYNC 1 > +#define I2S_FMT_SHIFT 12 > +#define I2S_CTRL_FRAME_FMT_MASK (7 << I2S_FMT_SHIFT) > +#define I2S_CTRL_FRAME_FMT_LRCK_MODE (I2S_FMT_LRCK << I2S_FMT_SHIFT) > +#define I2S_CTRL_FRAME_FMT_FSYNC_MODE (I2S_FMT_FSYNC << I2S_FMT_SHIFT) > + > +#define I2S_CTRL_MASTER_EN_SHIFT 10 > +#define I2S_CTRL_MASTER_EN_MASK (1 << I2S_CTRL_MASTER_EN_SHIFT) > +#define I2S_CTRL_MASTER_EN (1 << I2S_CTRL_MASTER_EN_SHIFT) > + > +#define I2S_CTRL_LRCK_POL_SHIFT 9 > +#define I2S_CTRL_LRCK_POL_MASK (1 << I2S_CTRL_LRCK_POL_SHIFT) > +#define I2S_CTRL_LRCK_POL_LOW (0 << I2S_CTRL_LRCK_POL_SHIFT) > +#define I2S_CTRL_LRCK_POL_HIGH (1 << I2S_CTRL_LRCK_POL_SHIFT) > + > +#define I2S_CTRL_LPBK_SHIFT 8 > +#define I2S_CTRL_LPBK_MASK (1 << I2S_CTRL_LPBK_SHIFT) > +#define I2S_CTRL_LPBK_EN (1 << I2S_CTRL_LPBK_SHIFT) > + > +#define I2S_BITS_8 1 > +#define I2S_BITS_16 3 > +#define I2S_BITS_32 7 > +#define I2S_CTRL_BIT_SIZE_MASK 0x7 > + > +#define I2S_TIMING_CH_BIT_CNT_MASK 0x7ff > +#define I2S_TIMING_CH_BIT_CNT_SHIFT 0 > + > +#define I2S_SOFT_RESET_SHIFT 0 > +#define I2S_SOFT_RESET_MASK (1 << I2S_SOFT_RESET_SHIFT) > +#define I2S_SOFT_RESET_EN (1 << I2S_SOFT_RESET_SHIFT) > + > +#define I2S_RX_FIFO_DEPTH 64 > +#define DEFAULT_I2S_RX_FIFO_THRESHOLD 3 > + > +#define DEFAULT_I2S_SLOT_MASK 0xffff > + > +enum tegra210_i2s_path { > + I2S_RX_PATH, > + I2S_TX_PATH, > + I2S_PATHS, > +}; > + > +struct tegra210_i2s { > + struct clk *clk_i2s; > + struct clk *clk_sync_input; > + struct regmap *regmap; > + unsigned int stereo_to_mono[I2S_PATHS]; > + unsigned int mono_to_stereo[I2S_PATHS]; > + unsigned int audio_ch_override[I2S_PATHS]; > + unsigned int audio_fmt_override[I2S_PATHS]; > + /* Client overrides are common for TX and RX paths */ > + unsigned int client_ch_override; > + unsigned int client_fmt_override; > + unsigned int srate_override; > + unsigned int dai_fmt; > + unsigned int fsync_width; > + unsigned int bclk_ratio; > + unsigned int tx_mask; > + unsigned int rx_mask; > + int rx_fifo_th; Could rx_fifo_th be negative? > + bool loopback; > +}; > + > +#endif > 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=-8.0 required=3.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 D6AAEC33CAA for ; Tue, 21 Jan 2020 05:16:56 +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 3992124653 for ; Tue, 21 Jan 2020 05:16:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="d3pz8z7q"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FgHM4+d2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3992124653 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-devel-bounces@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 79CDD166F; Tue, 21 Jan 2020 06:16:04 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 79CDD166F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1579583814; bh=XYT5qk043pJmk/OmOJfDTLEK8pAQEdezwOMiXvbNMGQ=; h=To:References:From:Date:In-Reply-To:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=d3pz8z7qnI886j4sDirhcouDaxQ9LAM9Q7wUnGTbKKsJY1X/6vU7O2rHnqspv8Alx FHQgxRKnhoeHD5d1dQsstcywZTH92rzGqUGS3MGdTGRg168h/U4FIFPQy9KeJO8s+r qy9pDHGXR5E4LCWTO3HS5dnXzzIw+xV+WyW9EqrI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 88AA1F8015B; Tue, 21 Jan 2020 06:16:03 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id ACBD9F801D9; Tue, 21 Jan 2020 06:16:00 +0100 (CET) Received: from mail-ed1-x543.google.com (mail-ed1-x543.google.com [IPv6:2a00:1450:4864:20::543]) (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 4941DF800CB for ; Tue, 21 Jan 2020 06:15:52 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4941DF800CB Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FgHM4+d2" Received: by mail-ed1-x543.google.com with SMTP id dc19so1705577edb.10 for ; Mon, 20 Jan 2020 21:15:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=klMSGDQJKsoyQr3Lsdxy3UYH8nr788QDCt38oDW6BFM=; b=FgHM4+d2LF7TKlFnlms7ifEpOydBooj7i3ti7aouiV+MUU6RTtRtHkiOwazeEbospe XLTvaiOFKPxFivEejlxcA+T2pdYomXnAh64Xkzj2CY0FGQwpm5o7IGZ2L5vFilM7zl6C FF4dq8Y8gB6C+B+DOkOHNKDou4AmduOWOWul+03vjB7f3NLsSkrZMxmtSXwZWJr/s5PU NuArYGBxIWXWGSyyl9VxHQZucMgOfe5lcig+N9IxGCMtHbquFyCfgk64Cj23WnGCmMZM N0bhnIirl+W4vOZR8jBHOCQV7AZe8Z/mL7f+FdSjARuV7sDScXoHttQIRMeGU2ZiOKfj ISmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=klMSGDQJKsoyQr3Lsdxy3UYH8nr788QDCt38oDW6BFM=; b=pVDdO/NDgAE30C3UV9wNVUmRffPqfzyHOmxQHsr4YWpGePJwVHM854ttFIQaB6myUO HDzqBucbuWd+L8ysXKKOqfXAiOoQiLjl9T6vSE/cbgeetb5mYPD49liBycQYE3h33ZUq Jc5EaHyvlOHOvA/+FCp82rKPFDoOFfSTiwQ08q9kB5Kft313/OJb/pFA+1jaO8RbX8Wc hDvIl6hzZF4Q0jzJr0w6VwiiBNab5YAref/JmMM9hHWvj6lmvLixcyFNIddm7szjS3gP lNOhcVnOmwK/WFpC93XwBoG7ezqMvMDYheq+OV1W2YXxth/YdjW0XmpoBMhdkmw4Mrsh m0VA== X-Gm-Message-State: APjAAAXZtOfUgESdITS1Fw8pLj1cn6BE+r75ZvjTT0Z7a+4ohy2JmY39 loxEGR057JEjUlmxvUCJiKk= X-Google-Smtp-Source: APXvYqxb+qf+gpZ4j8GxxiLjWJBcGBZywN82BxD2oqWVvsrMDgySzmrCPtxi7JquKFmY4NdU+7Hk4A== X-Received: by 2002:a17:906:f241:: with SMTP id gy1mr2756175ejb.340.1579583751684; Mon, 20 Jan 2020 21:15:51 -0800 (PST) Received: from [192.168.2.145] (79-139-233-37.dynamic.spd-mgts.ru. [79.139.233.37]) by smtp.googlemail.com with ESMTPSA id w10sm1398631eds.69.2020.01.20.21.15.49 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 20 Jan 2020 21:15:51 -0800 (PST) To: Sameer Pujar , perex@perex.cz, tiwai@suse.com, robh+dt@kernel.org References: <1579530198-13431-1-git-send-email-spujar@nvidia.com> <1579530198-13431-5-git-send-email-spujar@nvidia.com> From: Dmitry Osipenko Message-ID: Date: Tue, 21 Jan 2020 08:15:47 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.3.0 MIME-Version: 1.0 In-Reply-To: <1579530198-13431-5-git-send-email-spujar@nvidia.com> Content-Language: en-US Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, jonathanh@nvidia.com, viswanathl@nvidia.com, linux-tegra@vger.kernel.org, broonie@kernel.org, atalambedu@nvidia.com, sharadg@nvidia.com, thierry.reding@gmail.com, rlokhande@nvidia.com, mkumard@nvidia.com, dramesh@nvidia.com Subject: Re: [alsa-devel] [PATCH 4/9] ASoC: tegra: add Tegra210 based I2S driver 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: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" MjAuMDEuMjAyMCAxNzoyMywgU2FtZWVyIFB1amFyINC/0LjRiNC10YI6Cj4gVGhlIEludGVyLUlD IFNvdW5kIChJMlMpIGNvbnRyb2xsZXIgaW1wbGVtZW50cyBmdWxsLWR1cGxleCwgYmktZGlyZWN0 aW9uYWwKPiBhbmQgc2luZ2xlIGRpcmVjdGlvbiBwb2ludCB0byBwb2ludCBzZXJpYWwgaW50ZXJm YWNlLiBJdCBjYW4gaW50ZXJmYWNlCj4gd2l0aCBJMlMgY29tcGF0aWJsZSBkZXZpY2VzLiBUZWdy YSBJMlMgY29udHJvbGxlciBjYW4gb3BlcmF0ZSBhcyBib3RoCj4gbWFzdGVyIGFuZCBzbGF2ZS4K PiAKPiBUaGlzIHBhdGNoIHJlZ2lzdGVycyBJMlMgY29udHJvbGxlciB3aXRoIEFTb0MgZnJhbWV3 b3JrLiBUaGUgY29tcG9uZW50Cj4gZHJpdmVyIGV4cG9zZXMgREFQTSB3aWRnZXRzLCByb3V0ZXMg YW5kIGtjb250cm9scyBmb3IgdGhlIGRldmljZS4gVGhlIERBSQo+IGRyaXZlciBleHBvc2VzIEky UyBpbnRlcmZhY2VzLCB3aGljaCBjYW4gYmUgdXNlZCB0byBjb25uZWN0IGRpZmZlcmVudAo+IGNv bXBvbmVudHMgaW4gdGhlIEFTb0MgbGF5ZXIuIE1ha2VmaWxlIGFuZCBLY29uZmlnIHN1cHBvcnQg aXMgYWRkZWQgdG8KPiBhbGxvdyB0byBidWlsZCB0aGUgZHJpdmVyLiBUaGUgSTJTIGRldmljZXMg Y2FuIGJlIGVuYWJsZWQgaW4gdGhlIERUIHZpYQo+ICJudmlkaWEsdGVncmEyMTAtaTJzIiBjb21w YXRpYmxlIGJpbmRpbmcuCj4gCj4gU2lnbmVkLW9mZi1ieTogU2FtZWVyIFB1amFyIDxzcHVqYXJA bnZpZGlhLmNvbT4KPiAtLS0KPiAgc291bmQvc29jL3RlZ3JhL0tjb25maWcgICAgICAgIHwgIDEw ICsKPiAgc291bmQvc29jL3RlZ3JhL01ha2VmaWxlICAgICAgIHwgICAyICsKPiAgc291bmQvc29j L3RlZ3JhL3RlZ3JhMjEwX2kycy5jIHwgOTQxICsrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrCj4gIHNvdW5kL3NvYy90ZWdyYS90ZWdyYTIxMF9pMnMuaCB8IDEzMiArKysr KysKPiAgNCBmaWxlcyBjaGFuZ2VkLCAxMDg1IGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUg MTAwNjQ0IHNvdW5kL3NvYy90ZWdyYS90ZWdyYTIxMF9pMnMuYwo+ICBjcmVhdGUgbW9kZSAxMDA2 NDQgc291bmQvc29jL3RlZ3JhL3RlZ3JhMjEwX2kycy5oCj4gCj4gZGlmZiAtLWdpdCBhL3NvdW5k L3NvYy90ZWdyYS9LY29uZmlnIGIvc291bmQvc29jL3RlZ3JhL0tjb25maWcKPiBpbmRleCAyYmRl MWU2Li4xNTdmYTdhIDEwMDY0NAo+IC0tLSBhL3NvdW5kL3NvYy90ZWdyYS9LY29uZmlnCj4gKysr IGIvc291bmQvc29jL3RlZ3JhL0tjb25maWcKPiBAQCAtNzMsNiArNzMsMTYgQEAgY29uZmlnIFNO RF9TT0NfVEVHUkEyMTBfRE1JQwo+ICAgICAgICAgICAgUERNIHJlY2VpdmVyLgo+ICAgICAgICAg ICAgU2F5IFkgb3IgTSBpZiB5b3Ugd2FudCB0byBhZGQgc3VwcG9ydCBmb3IgVGVncmEyMTAgRE1J QyBtb2R1bGUuCj4gIAo+ICtjb25maWcgU05EX1NPQ19URUdSQTIxMF9JMlMKPiArICAgICAgICB0 cmlzdGF0ZSAiVGVncmEyMTAgSTJTIG1vZHVsZSIKPiArICAgICAgICBkZXBlbmRzIG9uIFNORF9T T0NfVEVHUkEKPiArICAgICAgICBoZWxwCj4gKyAgICAgICAgICBDb25maWcgdG8gZW5hYmxlIHRo ZSBJbnRlci1JQyBTb3VuZCAoSTJTKSBDb250cm9sbGVyIHdoaWNoCj4gKyAgICAgICAgICBpbXBs ZW1lbnRzIGZ1bGwtZHVwbGV4IGFuZCBiaWRpcmVjdGlvbmFsIGFuZCBzaW5nbGUgZGlyZWN0aW9u Cj4gKyAgICAgICAgICBwb2ludC10by1wb2ludCBzZXJpYWwgaW50ZXJmYWNlcy4gSXQgY2FuIGlu dGVyZmFjZSB3aXRoIEkyUwo+ICsgICAgICAgICAgY29tcGF0aWJsZSBkZXZpY2VzLgo+ICsgICAg ICAgICAgU2F5IFkgb3IgTSBpZiB5b3Ugd2FudCB0byBhZGQgc3VwcG9ydCBmb3IgVGVncmEyMTAg STJTIG1vZHVsZS4KPiArCj4gIGNvbmZpZyBTTkRfU09DX1RFR1JBX1JUNTY0MAo+ICAJdHJpc3Rh dGUgIlNvQyBBdWRpbyBzdXBwb3J0IGZvciBUZWdyYSBib2FyZHMgdXNpbmcgYW4gUlQ1NjQwIGNv ZGVjIgo+ICAJZGVwZW5kcyBvbiBTTkRfU09DX1RFR1JBICYmIEkyQyAmJiBHUElPTElCCj4gZGlm ZiAtLWdpdCBhL3NvdW5kL3NvYy90ZWdyYS9NYWtlZmlsZSBiL3NvdW5kL3NvYy90ZWdyYS9NYWtl ZmlsZQo+IGluZGV4IDllNzhmZTQuLjFjNDQ1N2QgMTAwNjQ0Cj4gLS0tIGEvc291bmQvc29jL3Rl Z3JhL01ha2VmaWxlCj4gKysrIGIvc291bmQvc29jL3RlZ3JhL01ha2VmaWxlCj4gQEAgLTEwLDYg KzEwLDcgQEAgc25kLXNvYy10ZWdyYTMwLWFodWItb2JqcyA6PSB0ZWdyYTMwX2FodWIubwo+ICBz bmQtc29jLXRlZ3JhMzAtaTJzLW9ianMgOj0gdGVncmEzMF9pMnMubwo+ICBzbmQtc29jLXRlZ3Jh LWNpZi1vYmpzIDo9IHRlZ3JhX2NpZi5vCj4gIHNuZC1zb2MtdGVncmEyMTAtZG1pYy1vYmpzIDo9 IHRlZ3JhMjEwX2RtaWMubwo+ICtzbmQtc29jLXRlZ3JhMjEwLWkycy1vYmpzIDo9IHRlZ3JhMjEw X2kycy5vCj4gIAo+ICBvYmotJChDT05GSUdfU05EX1NPQ19URUdSQSkgKz0gc25kLXNvYy10ZWdy YS1wY20ubwo+ICBvYmotJChDT05GSUdfU05EX1NPQ19URUdSQSkgKz0gc25kLXNvYy10ZWdyYS11 dGlscy5vCj4gQEAgLTIxLDYgKzIyLDcgQEAgb2JqLSQoQ09ORklHX1NORF9TT0NfVEVHUkEyMF9T UERJRikgKz0gc25kLXNvYy10ZWdyYTIwLXNwZGlmLm8KPiAgb2JqLSQoQ09ORklHX1NORF9TT0Nf VEVHUkEzMF9BSFVCKSArPSBzbmQtc29jLXRlZ3JhMzAtYWh1Yi5vCj4gIG9iai0kKENPTkZJR19T TkRfU09DX1RFR1JBMzBfSTJTKSArPSBzbmQtc29jLXRlZ3JhMzAtaTJzLm8KPiAgb2JqLSQoQ09O RklHX1NORF9TT0NfVEVHUkEyMTBfRE1JQykgKz0gc25kLXNvYy10ZWdyYTIxMC1kbWljLm8KPiAr b2JqLSQoQ09ORklHX1NORF9TT0NfVEVHUkEyMTBfSTJTKSArPSBzbmQtc29jLXRlZ3JhMjEwLWky cy5vCj4gIAo+ICAjIFRlZ3JhIG1hY2hpbmUgU3VwcG9ydAo+ICBzbmQtc29jLXRlZ3JhLXJ0NTY0 MC1vYmpzIDo9IHRlZ3JhX3J0NTY0MC5vCj4gZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy90ZWdyYS90 ZWdyYTIxMF9pMnMuYyBiL3NvdW5kL3NvYy90ZWdyYS90ZWdyYTIxMF9pMnMuYwo+IG5ldyBmaWxl IG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uMzZlOGE3Ywo+IC0tLSAvZGV2L251bGwKPiAr KysgYi9zb3VuZC9zb2MvdGVncmEvdGVncmEyMTBfaTJzLmMKPiBAQCAtMCwwICsxLDk0MSBAQAo+ ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMC1vbmx5Cj4gKy8qCj4gKyAqIHRl Z3JhMjEwX2kycy5jIC0gVGVncmEyMTAgSTJTIGRyaXZlcgo+ICsgKgo+ICsgKiBDb3B5cmlnaHQg KGMpIDIwMjAgTlZJRElBIENPUlBPUkFUSU9OLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KPiArICoK PiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNs dWRlIDxsaW51eC9wbV9ydW50aW1lLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4K PiArI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+ Cj4gKyNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+ ICsjaW5jbHVkZSA8c291bmQvcGNtX3BhcmFtcy5oPgo+ICsjaW5jbHVkZSA8c291bmQvY29yZS5o Pgo+ICsjaW5jbHVkZSA8c291bmQvc29jLmg+Cj4gKyNpbmNsdWRlICJ0ZWdyYTIxMF9pMnMuaCIK PiArI2luY2x1ZGUgInRlZ3JhX2NpZi5oIgoKSGVhZGVycyBzaG91bGQgYmUgc29ydGVkIGluIGFs cGhhYmV0IG9yZGVyIHRvIGF2b2lkIGNvbmZ1c2lvbiBhYm91dCBob3cKdG8gaW5zZXJ0IGEgbmV3 IGhlYWRlci4KCj4gKyNkZWZpbmUgRFJWX05BTUUgInRlZ3JhMjEwLWkycyIKPiArCj4gK3N0YXRp YyBjb25zdCBzdHJ1Y3QgcmVnX2RlZmF1bHQgdGVncmEyMTBfaTJzX3JlZ19kZWZhdWx0c1tdID0g ewo+ICsJeyBURUdSQTIxMF9JMlNfUlhfSU5UX01BU0ssIDB4MDAwMDAwMDN9LAo+ICsJeyBURUdS QTIxMF9JMlNfUlhfQ0lGX0NUUkwsIDB4MDAwMDc3MDB9LAo+ICsJeyBURUdSQTIxMF9JMlNfVFhf SU5UX01BU0ssIDB4MDAwMDAwMDN9LAo+ICsJeyBURUdSQTIxMF9JMlNfVFhfQ0lGX0NUUkwsIDB4 MDAwMDc3MDB9LAo+ICsJeyBURUdSQTIxMF9JMlNfQ0csIDB4MX0sCj4gKwl7IFRFR1JBMjEwX0ky U19USU1JTkcsIDB4MDAwMDAwMWZ9LAo+ICsJeyBURUdSQTIxMF9JMlNfRU5BQkxFLCAweDF9LAo+ ICsJLyoKPiArCSAqIEJlbG93IHVwZGF0ZSBkb2VzIG5vdCBoYXZlIGFueSBlZmZlY3Qgb24gVGVn cmExODYgYW5kIFRlZ3JhMTk0Lgo+ICsJICogT24gVGVncmEyMTAsIEkyUzQgaGFzICJpMnM0YSIg YW5kICJpMnM0YiIgcGlucyBhbmQgYmVsb3cgdXBkYXRlCj4gKwkgKiBpcyByZXF1aXJlZCB0byBz ZWxlY3QgaTJzNGIgZm9yIGl0IHRvIGJlIGZ1bmN0aW9uYWwgZm9yIEkyUwo+ICsJICogb3BlcmF0 aW9uLgo+ICsJICovCj4gKwl7IFRFR1JBMjEwX0kyU19DWUEsIDB4MX0sCj4gK307Cj4gKwo+ICtz dGF0aWMgdm9pZCB0ZWdyYTIxMF9pMnNfc2V0X3Nsb3RfY3RybChzdHJ1Y3QgcmVnbWFwICpyZWdt YXAsCj4gKwkJCQkgICAgICAgdW5zaWduZWQgaW50IHRvdGFsX3Nsb3RzLAo+ICsJCQkJICAgICAg IHVuc2lnbmVkIGludCB0eF9zbG90X21hc2ssCj4gKwkJCQkgICAgICAgdW5zaWduZWQgaW50IHJ4 X3Nsb3RfbWFzaykKPiArewo+ICsJcmVnbWFwX3dyaXRlKHJlZ21hcCwgVEVHUkEyMTBfSTJTX1NM T1RfQ1RSTCwgdG90YWxfc2xvdHMgLSAxKTsKPiArCXJlZ21hcF93cml0ZShyZWdtYXAsIFRFR1JB MjEwX0kyU19UWF9TTE9UX0NUUkwsIHR4X3Nsb3RfbWFzayk7Cj4gKwlyZWdtYXBfd3JpdGUocmVn bWFwLCBURUdSQTIxMF9JMlNfUlhfU0xPVF9DVFJMLCByeF9zbG90X21hc2spOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19zZXRfY2xvY2tfcmF0ZShzdHJ1Y3QgZGV2aWNlICpk ZXYsCj4gKwkJCQkgICAgICAgdW5zaWduZWQgaW50IGNsb2NrX3JhdGUpCj4gK3sKPiArCXN0cnVj dCB0ZWdyYTIxMF9pMnMgKmkycyA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJdW5zaWduZWQg aW50IHZhbDsKPiArCWludCByZXQ7Cj4gKwo+ICsJcmVnbWFwX3JlYWQoaTJzLT5yZWdtYXAsIFRF R1JBMjEwX0kyU19DVFJMLCAmdmFsKTsKPiArCj4gKwkvKiBObyBuZWVkIHRvIHNldCByYXRlcyBp ZiBJMlMgaXMgYmVpbmcgb3BlcmF0ZWQgaW4gc2xhdmUgKi8KPiArCWlmICghKHZhbCAmIEkyU19D VFJMX01BU1RFUl9FTikpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJcmV0ID0gY2xrX3NldF9yYXRl KGkycy0+Y2xrX2kycywgY2xvY2tfcmF0ZSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vycihk ZXYsICJmYWlsZWQgdG8gc2V0IEkyUyBiaXQgY2xvY2sgcmF0ZSAldSwgZXJyOiAlZFxuIiwKPiAr CQkJY2xvY2tfcmF0ZSwgcmV0KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCWlmICgh SVNfRVJSKGkycy0+Y2xrX3N5bmNfaW5wdXQpKSB7Cj4gKwkJLyoKPiArCQkgKiBPdGhlciBJL08g bW9kdWxlcyBpbiBBSFVCIGNhbiB1c2UgaTJzIGJjbGsgYXMgcmVmZXJlbmNlCj4gKwkJICogY2xv Y2suIEJlbG93IHNldHMgc3luYyBpbnB1dCBjbG9jayByYXRlIGFzIHBlciBiY2xrLAo+ICsJCSAq IHdoaWNoIGNhbiBiZSB1c2VkIGFzIGlucHV0IHRvIG90aGVyIEkvTyBtb2R1bGVzLgo+ICsJCSAq Lwo+ICsJCXJldCA9IGNsa19zZXRfcmF0ZShpMnMtPmNsa19zeW5jX2lucHV0LCBjbG9ja19yYXRl KTsKPiArCQlpZiAocmV0KSB7Cj4gKwkJCWRldl9lcnIoZGV2LAo+ICsJCQkJImZhaWxlZCB0byBz ZXQgc3luYyBpbnB1dCByYXRlICV1LCBlcnIgPSAlZFxuIiwKPiArCQkJCWNsb2NrX3JhdGUsIHJl dCk7Cj4gKwkJCXJldHVybiByZXQ7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19zd19yZXNldChzdHJ1Y3Qgc25kX3NvY19j b21wb25lbnQgKmNvbXBudCwKPiArCQkJCSBib29sIGlzX3BsYXliYWNrKQo+ICt7Cj4gKwlzdHJ1 Y3QgZGV2aWNlICpkZXYgPSBjb21wbnQtPmRldjsKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmky cyA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJdW5zaWduZWQgaW50IHJlc2V0X21hc2sgPSBJ MlNfU09GVF9SRVNFVF9NQVNLOwo+ICsJdW5zaWduZWQgaW50IHJlc2V0X2VuID0gSTJTX1NPRlRf UkVTRVRfRU47Cj4gKwl1bnNpZ25lZCBpbnQgcmVzZXRfcmVnLCBjaWZfcmVnLCBzdHJlYW1fcmVn Owo+ICsJdW5zaWduZWQgaW50IGNpZl9jdHJsLCBzdHJlYW1fY3RybCwgaTJzX2N0cmwsIHZhbDsK PiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGlzX3BsYXliYWNrKSB7Cj4gKwkJcmVzZXRfcmVnID0g VEVHUkEyMTBfSTJTX1JYX1NPRlRfUkVTRVQ7Cj4gKwkJY2lmX3JlZyA9IFRFR1JBMjEwX0kyU19S WF9DSUZfQ1RSTDsKPiArCQlzdHJlYW1fcmVnID0gVEVHUkEyMTBfSTJTX1JYX0NUUkw7Cj4gKwl9 IGVsc2Ugewo+ICsJCXJlc2V0X3JlZyA9IFRFR1JBMjEwX0kyU19UWF9TT0ZUX1JFU0VUOwo+ICsJ CWNpZl9yZWcgPSBURUdSQTIxMF9JMlNfVFhfQ0lGX0NUUkw7Cj4gKwkJc3RyZWFtX3JlZyA9IFRF R1JBMjEwX0kyU19UWF9DVFJMOwo+ICsJfQo+ICsKPiArCS8qIFN0b3JlICovCj4gKwlyZWdtYXBf cmVhZChpMnMtPnJlZ21hcCwgY2lmX3JlZywgJmNpZl9jdHJsKTsKPiArCXJlZ21hcF9yZWFkKGky cy0+cmVnbWFwLCBzdHJlYW1fcmVnLCAmc3RyZWFtX2N0cmwpOwo+ICsJcmVnbWFwX3JlYWQoaTJz LT5yZWdtYXAsIFRFR1JBMjEwX0kyU19DVFJMLCAmaTJzX2N0cmwpOwo+ICsKPiArCS8qIFJlc2V0 ICovCj4gKwlyZWdtYXBfdXBkYXRlX2JpdHMoaTJzLT5yZWdtYXAsIHJlc2V0X3JlZywgcmVzZXRf bWFzaywgcmVzZXRfZW4pOwo+ICsKPiArCXJldCA9IHJlZ21hcF9yZWFkX3BvbGxfdGltZW91dChp MnMtPnJlZ21hcCwgcmVzZXRfcmVnLCB2YWwsCj4gKwkJCQkgICAgICAgISh2YWwgJiByZXNldF9t YXNrICYgcmVzZXRfZW4pLAo+ICsJCQkJICAgICAgIDEwLCAxMDAwMCk7Cj4gKwlpZiAocmV0IDwg MCkgewo+ICsJCWRldl9lcnIoZGV2LCAidGltZW91dDogZmFpbGVkIHRvIHJlc2V0IEkyUyBmb3Ig JXNcbiIsCj4gKwkJCWlzX3BsYXliYWNrID8gInBsYXliYWNrIiA6ICJjYXB0dXJlIik7Cj4gKwkJ cmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwkvKiBSZXN0b3JlICovCj4gKwlyZWdtYXBfd3JpdGUo aTJzLT5yZWdtYXAsIGNpZl9yZWcsIGNpZl9jdHJsKTsKPiArCXJlZ21hcF93cml0ZShpMnMtPnJl Z21hcCwgc3RyZWFtX3JlZywgc3RyZWFtX2N0cmwpOwo+ICsJcmVnbWFwX3dyaXRlKGkycy0+cmVn bWFwLCBURUdSQTIxMF9JMlNfQ1RSTCwgaTJzX2N0cmwpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19pbml0KHN0cnVjdCBzbmRfc29jX2RhcG1f d2lkZ2V0ICp3LAo+ICsJCQkgICAgIHN0cnVjdCBzbmRfa2NvbnRyb2wgKmtjb250cm9sLCBpbnQg ZXZlbnQpCj4gK3sKPiArCXN0cnVjdCBzbmRfc29jX2NvbXBvbmVudCAqY29tcG50ID0gc25kX3Nv Y19kYXBtX3RvX2NvbXBvbmVudCh3LT5kYXBtKTsKPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNv bXBudC0+ZGV2Owo+ICsJc3RydWN0IHRlZ3JhMjEwX2kycyAqaTJzID0gZGV2X2dldF9kcnZkYXRh KGRldik7Cj4gKwl1bnNpZ25lZCBpbnQgdmFsLCBzdGF0dXNfcmVnOwo+ICsJYm9vbCBpc19wbGF5 YmFjazsKPiArCWludCByZXQ7Cj4gKwo+ICsJc3dpdGNoICh3LT5yZWcpIHsKPiArCWNhc2UgVEVH UkEyMTBfSTJTX1JYX0VOQUJMRToKPiArCQlpc19wbGF5YmFjayA9IHRydWU7Cj4gKwkJc3RhdHVz X3JlZyA9IFRFR1JBMjEwX0kyU19SWF9TVEFUVVM7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFRFR1JB MjEwX0kyU19UWF9FTkFCTEU6Cj4gKwkJaXNfcGxheWJhY2sgPSBmYWxzZTsKPiArCQlzdGF0dXNf cmVnID0gVEVHUkEyMTBfSTJTX1RYX1NUQVRVUzsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4g KwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJLyogRW5zdXJlIEkyUyBpcyBpbiBkaXNh YmxlZCBzdGF0ZSBiZWZvcmUgbmV3IHNlc3Npb24gKi8KPiArCXJldCA9IHJlZ21hcF9yZWFkX3Bv bGxfdGltZW91dChpMnMtPnJlZ21hcCwgc3RhdHVzX3JlZywgdmFsLAo+ICsJCQkJICAgICAgICEo dmFsICYgSTJTX0VOX01BU0sgJiBJMlNfRU4pLAo+ICsJCQkJICAgICAgIDEwLCAxMDAwMCk7Cj4g KwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAidGltZW91dDogcHJldmlvdXMgSTJT ICVzIGlzIHN0aWxsIGFjdGl2ZVxuIiwKPiArCQkJaXNfcGxheWJhY2sgPyAicGxheWJhY2siIDog ImNhcHR1cmUiKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCS8qIFNXIHJlc2V0ICov CgpDb21tZW50cyBzaG91bGQgYW1lbmQgY29kZSB3aXRoIHVzZWZ1bCBpbmZvcm1hdGlvbi4KCj4g KwlyZXR1cm4gdGVncmEyMTBfaTJzX3N3X3Jlc2V0KGNvbXBudCwgaXNfcGxheWJhY2spOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19ydW50aW1lX3N1c3BlbmQoc3RydWN0IGRl dmljZSAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgdGVncmEyMTBfaTJzICppMnMgPSBkZXZfZ2V0X2Ry dmRhdGEoZGV2KTsKPiArCj4gKwlyZWdjYWNoZV9jYWNoZV9vbmx5KGkycy0+cmVnbWFwLCB0cnVl KTsKPiArCXJlZ2NhY2hlX21hcmtfZGlydHkoaTJzLT5yZWdtYXApOwo+ICsKPiArCWNsa19kaXNh YmxlX3VucHJlcGFyZShpMnMtPmNsa19pMnMpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19ydW50aW1lX3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpk ZXYpCj4gK3sKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmkycyA9IGRldl9nZXRfZHJ2ZGF0YShk ZXYpOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoaTJzLT5j bGtfaTJzKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBlbmFi bGUgSTJTIGJpdCBjbG9jaywgZXJyOiAlZFxuIiwgcmV0KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJ fQo+ICsKPiArCXJlZ2NhY2hlX2NhY2hlX29ubHkoaTJzLT5yZWdtYXAsIGZhbHNlKTsKPiArCXJl Z2NhY2hlX3N5bmMoaTJzLT5yZWdtYXApOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtz dGF0aWMgdm9pZCB0ZWdyYTIxMF9pMnNfc2V0X2RhdGFfb2Zmc2V0KHN0cnVjdCB0ZWdyYTIxMF9p MnMgKmkycywKPiArCQkJCQkgdW5zaWduZWQgaW50IGRhdGFfb2Zmc2V0KQo+ICt7Cj4gKwl1bnNp Z25lZCBpbnQgbWFzayA9IEkyU19DVFJMX0RBVEFfT0ZGU0VUX01BU0s7Cj4gKwl1bnNpZ25lZCBp bnQgc2hpZnQgPSBJMlNfREFUQV9TSElGVDsKPiArCXVuc2lnbmVkIGludCByZWc7Cj4gKwo+ICsJ cmVnID0gVEVHUkEyMTBfSTJTX1RYX0NUUkw7Cj4gKwlyZWdtYXBfdXBkYXRlX2JpdHMoaTJzLT5y ZWdtYXAsIHJlZywgbWFzaywgZGF0YV9vZmZzZXQgPDwgc2hpZnQpOwo+ICsKPiArCXJlZyA9IFRF R1JBMjEwX0kyU19SWF9DVFJMOwo+ICsJcmVnbWFwX3VwZGF0ZV9iaXRzKGkycy0+cmVnbWFwLCBy ZWcsIG1hc2ssIGRhdGFfb2Zmc2V0IDw8IHNoaWZ0KTsKPiArfQo+ICsKPiArc3RhdGljIGludCB0 ZWdyYTIxMF9pMnNfc2V0X2ZtdChzdHJ1Y3Qgc25kX3NvY19kYWkgKmRhaSwKPiArCQkJCXVuc2ln bmVkIGludCBmbXQpCj4gK3sKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmkycyA9IHNuZF9zb2Nf ZGFpX2dldF9kcnZkYXRhKGRhaSk7Cj4gKwl1bnNpZ25lZCBpbnQgbWFzaywgdmFsOwo+ICsKPiAr CW1hc2sgPSBJMlNfQ1RSTF9NQVNURVJfRU5fTUFTSzsKPiArCXN3aXRjaCAoZm10ICYgU05EX1NP Q19EQUlGTVRfTUFTVEVSX01BU0spIHsKPiArCWNhc2UgU05EX1NPQ19EQUlGTVRfQ0JTX0NGUzoK PiArCQl2YWwgPSAwOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9DQk1fQ0ZN Ogo+ICsJCXZhbCA9IEkyU19DVFJMX01BU1RFUl9FTjsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6 Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJbWFzayB8PSBJMlNfQ1RSTF9GUkFN RV9GTVRfTUFTSyB8IEkyU19DVFJMX0xSQ0tfUE9MX01BU0s7Cj4gKwlzd2l0Y2ggKGZtdCAmIFNO RF9TT0NfREFJRk1UX0ZPUk1BVF9NQVNLKSB7Cj4gKwljYXNlIFNORF9TT0NfREFJRk1UX0RTUF9B Ogo+ICsJCXZhbCB8PSBJMlNfQ1RSTF9GUkFNRV9GTVRfRlNZTkNfTU9ERTsKPiArCQl2YWwgfD0g STJTX0NUUkxfTFJDS19QT0xfSElHSDsKPiArCQl0ZWdyYTIxMF9pMnNfc2V0X2RhdGFfb2Zmc2V0 KGkycywgMSk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFNORF9TT0NfREFJRk1UX0RTUF9COgo+ICsJ CXZhbCB8PSBJMlNfQ1RSTF9GUkFNRV9GTVRfRlNZTkNfTU9ERTsKPiArCQl2YWwgfD0gSTJTX0NU UkxfTFJDS19QT0xfSElHSDsKPiArCQl0ZWdyYTIxMF9pMnNfc2V0X2RhdGFfb2Zmc2V0KGkycywg MCk7Cj4gKwkJYnJlYWs7Cj4gKwkvKiBJMlMgbW9kZSBoYXMgZGF0YSBvZmZzZXQgb2YgMSAqLwo+ ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9JMlM6Cj4gKwkJdmFsIHw9IEkyU19DVFJMX0ZSQU1FX0ZN VF9MUkNLX01PREU7Cj4gKwkJdmFsIHw9IEkyU19DVFJMX0xSQ0tfUE9MX0xPVzsKPiArCQl0ZWdy YTIxMF9pMnNfc2V0X2RhdGFfb2Zmc2V0KGkycywgMSk7Cj4gKwkJYnJlYWs7Cj4gKwkvKgo+ICsJ ICogRm9yIFJKIG1vZGUgZGF0YSBvZmZzZXQgaXMgZGVwZW5kZW50IG9uIHRoZSBzYW1wbGUgc2l6 ZQo+ICsJICogYW5kIHRoZSBiY2xrIHJhdGlvLCBhbmQgc28gaXMgc2V0IHdoZW4gaHdfcGFyYW1z IGlzIGNhbGxlZC4KPiArCSAqLwo+ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9SSUdIVF9KOgo+ICsJ CXZhbCB8PSBJMlNfQ1RSTF9GUkFNRV9GTVRfTFJDS19NT0RFOwo+ICsJCXZhbCB8PSBJMlNfQ1RS TF9MUkNLX1BPTF9ISUdIOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9MRUZU X0o6Cj4gKwkJdmFsIHw9IEkyU19DVFJMX0ZSQU1FX0ZNVF9MUkNLX01PREU7Cj4gKwkJdmFsIHw9 IEkyU19DVFJMX0xSQ0tfUE9MX0hJR0g7Cj4gKwkJdGVncmEyMTBfaTJzX3NldF9kYXRhX29mZnNl dChpMnMsIDApOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gLUVJTlZBTDsK PiArCX0KPiArCj4gKwltYXNrIHw9IEkyU19DVFJMX0VER0VfQ1RSTF9NQVNLOwo+ICsJc3dpdGNo IChmbXQgJiBTTkRfU09DX0RBSUZNVF9JTlZfTUFTSykgewo+ICsJY2FzZSBTTkRfU09DX0RBSUZN VF9OQl9ORjoKPiArCQl2YWwgfD0gSTJTX0NUUkxfRURHRV9DVFJMX1BPU19FREdFOwo+ICsJCWJy ZWFrOwo+ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9OQl9JRjoKPiArCQl2YWwgfD0gSTJTX0NUUkxf RURHRV9DVFJMX1BPU19FREdFOwo+ICsJCXZhbCBePSBJMlNfQ1RSTF9MUkNLX1BPTF9NQVNLOwo+ ICsJCWJyZWFrOwo+ICsJY2FzZSBTTkRfU09DX0RBSUZNVF9JQl9ORjoKPiArCQl2YWwgfD0gSTJT X0NUUkxfRURHRV9DVFJMX05FR19FREdFOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTTkRfU09DX0RB SUZNVF9JQl9JRjoKPiArCQl2YWwgfD0gSTJTX0NUUkxfRURHRV9DVFJMX05FR19FREdFOwo+ICsJ CXZhbCBePSBJMlNfQ1RSTF9MUkNLX1BPTF9NQVNLOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZWdtYXBfdXBkYXRlX2JpdHMoaTJz LT5yZWdtYXAsIFRFR1JBMjEwX0kyU19DVFJMLCBtYXNrLCB2YWwpOwo+ICsKPiArCWkycy0+ZGFp X2ZtdCA9IGZtdCAmIFNORF9TT0NfREFJRk1UX0ZPUk1BVF9NQVNLOwo+ICsKPiArCXJldHVybiAw Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19zZXRfdGRtX3Nsb3Qoc3RydWN0 IHNuZF9zb2NfZGFpICpkYWksCj4gKwkJCQkgICAgIHVuc2lnbmVkIGludCB0eF9tYXNrLCB1bnNp Z25lZCBpbnQgcnhfbWFzaywKPiArCQkJCSAgICAgaW50IHNsb3RzLCBpbnQgc2xvdF93aWR0aCkK PiArewo+ICsJc3RydWN0IHRlZ3JhMjEwX2kycyAqaTJzID0gc25kX3NvY19kYWlfZ2V0X2RydmRh dGEoZGFpKTsKPiArCj4gKwkvKiBDb3B5IHRoZSByZXF1aXJlZCB0eCBhbmQgcnggbWFzayAqLwo+ ICsJaTJzLT50eF9tYXNrID0gKHR4X21hc2sgPiBERUZBVUxUX0kyU19TTE9UX01BU0spID8KPiAr CQkgICAgICAgREVGQVVMVF9JMlNfU0xPVF9NQVNLIDogdHhfbWFzazsKPiArCWkycy0+cnhfbWFz ayA9IChyeF9tYXNrID4gREVGQVVMVF9JMlNfU0xPVF9NQVNLKSA/Cj4gKwkJICAgICAgIERFRkFV TFRfSTJTX1NMT1RfTUFTSyA6IHJ4X21hc2s7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4g K3N0YXRpYyBpbnQgdGVncmEyMTBfaTJzX3NldF9kYWlfYmNsa19yYXRpbyhzdHJ1Y3Qgc25kX3Nv Y19kYWkgKmRhaSwKPiArCQkJCQkgICB1bnNpZ25lZCBpbnQgcmF0aW8pCj4gK3sKPiArCXN0cnVj dCB0ZWdyYTIxMF9pMnMgKmkycyA9IHNuZF9zb2NfZGFpX2dldF9kcnZkYXRhKGRhaSk7Cj4gKwo+ ICsJaTJzLT5iY2xrX3JhdGlvID0gcmF0aW87Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4g K3N0YXRpYyBpbnQgdGVncmEyMTBfaTJzX2dldF9jb250cm9sKHN0cnVjdCBzbmRfa2NvbnRyb2wg Kmtjb250cm9sLAo+ICsJCQkJICAgIHN0cnVjdCBzbmRfY3RsX2VsZW1fdmFsdWUgKnVjb250cm9s KQo+ICt7Cj4gKwlzdHJ1Y3Qgc25kX3NvY19jb21wb25lbnQgKmNvbXBudCA9IHNuZF9zb2Nfa2Nv bnRyb2xfY29tcG9uZW50KGtjb250cm9sKTsKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmkycyA9 IHNuZF9zb2NfY29tcG9uZW50X2dldF9kcnZkYXRhKGNvbXBudCk7Cj4gKwlsb25nICp1Y3RsX3Zh bCA9ICZ1Y29udHJvbC0+dmFsdWUuaW50ZWdlci52YWx1ZVswXTsKPiArCj4gKwlpZiAoc3Ryc3Ry KGtjb250cm9sLT5pZC5uYW1lLCAiTG9vcGJhY2siKSkKPiArCQkqdWN0bF92YWwgPSBpMnMtPmxv b3BiYWNrOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiU2FtcGxlIFJh dGUiKSkKPiArCQkqdWN0bF92YWwgPSBpMnMtPnNyYXRlX292ZXJyaWRlOwo+ICsJZWxzZSBpZiAo c3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiRlNZTkMgV2lkdGgiKSkKPiArCQkqdWN0bF92YWwg PSBpMnMtPmZzeW5jX3dpZHRoOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1l LCAiUGxheWJhY2sgQXVkaW8gQml0IEZvcm1hdCIpKQo+ICsJCSp1Y3RsX3ZhbCA9IGkycy0+YXVk aW9fZm10X292ZXJyaWRlW0kyU19SWF9QQVRIXTsKPiArCWVsc2UgaWYgKHN0cnN0cihrY29udHJv bC0+aWQubmFtZSwgIkNhcHR1cmUgQXVkaW8gQml0IEZvcm1hdCIpKQo+ICsJCSp1Y3RsX3ZhbCA9 IGkycy0+YXVkaW9fZm10X292ZXJyaWRlW0kyU19UWF9QQVRIXTsKPiArCWVsc2UgaWYgKHN0cnN0 cihrY29udHJvbC0+aWQubmFtZSwgIkNsaWVudCBCaXQgRm9ybWF0IikpCj4gKwkJKnVjdGxfdmFs ID0gaTJzLT5jbGllbnRfZm10X292ZXJyaWRlOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9s LT5pZC5uYW1lLCAiUGxheWJhY2sgQXVkaW8gQ2hhbm5lbHMiKSkKPiArCQkqdWN0bF92YWwgPSBp MnMtPmF1ZGlvX2NoX292ZXJyaWRlW0kyU19SWF9QQVRIXTsKPiArCWVsc2UgaWYgKHN0cnN0cihr Y29udHJvbC0+aWQubmFtZSwgIkNhcHR1cmUgQXVkaW8gQ2hhbm5lbHMiKSkKPiArCQkqdWN0bF92 YWwgPSBpMnMtPmF1ZGlvX2NoX292ZXJyaWRlW0kyU19UWF9QQVRIXTsKPiArCWVsc2UgaWYgKHN0 cnN0cihrY29udHJvbC0+aWQubmFtZSwgIkNsaWVudCBDaGFubmVscyIpKQo+ICsJCSp1Y3RsX3Zh bCA9IGkycy0+Y2xpZW50X2NoX292ZXJyaWRlOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9s LT5pZC5uYW1lLCAiQ2FwdHVyZSBTdGVyZW8gVG8gTW9ubyIpKQo+ICsJCSp1Y3RsX3ZhbCA9IGky cy0+c3RlcmVvX3RvX21vbm9bSTJTX1RYX1BBVEhdOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250 cm9sLT5pZC5uYW1lLCAiQ2FwdHVyZSBNb25vIFRvIFN0ZXJlbyIpKQo+ICsJCSp1Y3RsX3ZhbCA9 IGkycy0+bW9ub190b19zdGVyZW9bSTJTX1RYX1BBVEhdOwo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtj b250cm9sLT5pZC5uYW1lLCAiUGxheWJhY2sgU3RlcmVvIFRvIE1vbm8iKSkKPiArCQkqdWN0bF92 YWwgPSBpMnMtPnN0ZXJlb190b19tb25vW0kyU19SWF9QQVRIXTsKPiArCWVsc2UgaWYgKHN0cnN0 cihrY29udHJvbC0+aWQubmFtZSwgIlBsYXliYWNrIE1vbm8gVG8gU3RlcmVvIikpCj4gKwkJKnVj dGxfdmFsID0gaTJzLT5tb25vX3RvX3N0ZXJlb1tJMlNfUlhfUEFUSF07Cj4gKwllbHNlIGlmIChz dHJzdHIoa2NvbnRyb2wtPmlkLm5hbWUsICJQbGF5YmFjayBGSUZPIFRocmVzaG9sZCIpKQo+ICsJ CSp1Y3RsX3ZhbCA9IGkycy0+cnhfZmlmb190aDsKPiArCWVsc2UgaWYgKHN0cnN0cihrY29udHJv bC0+aWQubmFtZSwgIkJDTEsgUmF0aW8iKSkKPiArCQkqdWN0bF92YWwgPSBpMnMtPmJjbGtfcmF0 aW87Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdGVncmEyMTBfaTJz X3B1dF9jb250cm9sKHN0cnVjdCBzbmRfa2NvbnRyb2wgKmtjb250cm9sLAo+ICsJc3RydWN0IHNu ZF9jdGxfZWxlbV92YWx1ZSAqdWNvbnRyb2wpCgpDaGVja3BhdGNoIHNob3VsZCBjb21wbGFpbiBh Ym91dCB0aGUgd3JvbmcgaW5kZW50YXRpb24gaGVyZS4KCj4gK3sKPiArCXN0cnVjdCBzbmRfc29j X2NvbXBvbmVudCAqY29tcG50ID0gc25kX3NvY19rY29udHJvbF9jb21wb25lbnQoa2NvbnRyb2wp Owo+ICsJc3RydWN0IHRlZ3JhMjEwX2kycyAqaTJzID0gc25kX3NvY19jb21wb25lbnRfZ2V0X2Ry dmRhdGEoY29tcG50KTsKPiArCWludCB2YWx1ZSA9IHVjb250cm9sLT52YWx1ZS5pbnRlZ2VyLnZh bHVlWzBdOwo+ICsKPiArCWlmIChzdHJzdHIoa2NvbnRyb2wtPmlkLm5hbWUsICJMb29wYmFjayIp KSB7Cj4gKwkJaTJzLT5sb29wYmFjayA9IHZhbHVlOwo+ICsKPiArCQlyZWdtYXBfdXBkYXRlX2Jp dHMoaTJzLT5yZWdtYXAsIFRFR1JBMjEwX0kyU19DVFJMLAo+ICsJCQkJICAgSTJTX0NUUkxfTFBC S19NQVNLLAo+ICsJCQkJICAgaTJzLT5sb29wYmFjayA8PCBJMlNfQ1RSTF9MUEJLX1NISUZUKTsK PiArCj4gKwl9IGVsc2UgaWYgKHN0cnN0cihrY29udHJvbC0+aWQubmFtZSwgIlNhbXBsZSBSYXRl IikpCj4gKwkJaTJzLT5zcmF0ZV9vdmVycmlkZSA9IHZhbHVlOwo+ICsJZWxzZSBpZiAoc3Ryc3Ry KGtjb250cm9sLT5pZC5uYW1lLCAiRlNZTkMgV2lkdGgiKSkgewo+ICsJCS8qCj4gKwkJICogRnJh bWUgc3luYyB3aWR0aCBpcyB1c2VkIG9ubHkgZm9yIEZTWU5DIG1vZGVzIGFuZCBub3QKPiArCQkg KiBhcHBsaWNhYmxlIGZvciBMUkNLIG1vZGVzLiBSZXNldCB2YWx1ZSBmb3IgdGhpcyBmaWVsZCBp cyAiMCIsCj4gKwkJICogd2hpY2ggbWVhbnMgdGhlIHdpZHRoIGlzIG9uZSBiaXQgY2xvY2sgd2lk ZS4KPiArCQkgKiBUaGUgd2lkdGggcmVxdWlyZW1lbnQgbWF5IGRlcGVuZCBvbiB0aGUgY29kZWMg YW5kIGluIHN1Y2gKPiArCQkgKiBjYXNlcyBtaXhlciBjb250cm9sIGlzIHVzZWQgdG8gdXBkYXRl IGN1c3RvbSB2YWx1ZXMuIEEgdmFsdWUKPiArCQkgKiBvZiAiTiIgaGVyZSBtZWFucywgd2lkdGgg aXMgIk4gKyAxIiBiaXQgY2xvY2sgd2lkZS4KPiArCQkgKi8KPiArCQlpMnMtPmZzeW5jX3dpZHRo ID0gdmFsdWU7Cj4gKwo+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpMnMtPnJlZ21hcCwgVEVHUkEy MTBfSTJTX0NUUkwsCj4gKwkJCQkgICBJMlNfQ1RSTF9GU1lOQ19XSURUSF9NQVNLLAo+ICsJCQkJ ICAgaTJzLT5mc3luY193aWR0aCA8PCBJMlNfRlNZTkNfV0lEVEhfU0hJRlQpOwo+ICsKPiArCX0g ZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiUGxheWJhY2sgQXVkaW8gQml0IEZv cm1hdCIpKQo+ICsJCWkycy0+YXVkaW9fZm10X292ZXJyaWRlW0kyU19SWF9QQVRIXSA9IHZhbHVl Owo+ICsJZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiQ2FwdHVyZSBBdWRpbyBC aXQgRm9ybWF0IikpCj4gKwkJaTJzLT5hdWRpb19mbXRfb3ZlcnJpZGVbSTJTX1RYX1BBVEhdID0g dmFsdWU7Cj4gKwllbHNlIGlmIChzdHJzdHIoa2NvbnRyb2wtPmlkLm5hbWUsICJDbGllbnQgQml0 IEZvcm1hdCIpKQo+ICsJCWkycy0+Y2xpZW50X2ZtdF9vdmVycmlkZSA9IHZhbHVlOwo+ICsJZWxz ZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiUGxheWJhY2sgQXVkaW8gQ2hhbm5lbHMi KSkKPiArCQlpMnMtPmF1ZGlvX2NoX292ZXJyaWRlW0kyU19SWF9QQVRIXSA9IHZhbHVlOwo+ICsJ ZWxzZSBpZiAoc3Ryc3RyKGtjb250cm9sLT5pZC5uYW1lLCAiQ2FwdHVyZSBBdWRpbyBDaGFubmVs cyIpKQo+ICsJCWkycy0+YXVkaW9fY2hfb3ZlcnJpZGVbSTJTX1RYX1BBVEhdID0gdmFsdWU7Cj4g KwllbHNlIGlmIChzdHJzdHIoa2NvbnRyb2wtPmlkLm5hbWUsICJDbGllbnQgQ2hhbm5lbHMiKSkK PiArCQlpMnMtPmNsaWVudF9jaF9vdmVycmlkZSA9IHZhbHVlOwo+ICsJZWxzZSBpZiAoc3Ryc3Ry KGtjb250cm9sLT5pZC5uYW1lLCAiQ2FwdHVyZSBTdGVyZW8gVG8gTW9ubyIpKQo+ICsJCWkycy0+ c3RlcmVvX3RvX21vbm9bSTJTX1RYX1BBVEhdID0gdmFsdWU7Cj4gKwllbHNlIGlmIChzdHJzdHIo a2NvbnRyb2wtPmlkLm5hbWUsICJDYXB0dXJlIE1vbm8gVG8gU3RlcmVvIikpCj4gKwkJaTJzLT5t b25vX3RvX3N0ZXJlb1tJMlNfVFhfUEFUSF0gPSB2YWx1ZTsKPiArCWVsc2UgaWYgKHN0cnN0cihr Y29udHJvbC0+aWQubmFtZSwgIlBsYXliYWNrIFN0ZXJlbyBUbyBNb25vIikpCj4gKwkJaTJzLT5z dGVyZW9fdG9fbW9ub1tJMlNfUlhfUEFUSF0gPSB2YWx1ZTsKPiArCWVsc2UgaWYgKHN0cnN0cihr Y29udHJvbC0+aWQubmFtZSwgIlBsYXliYWNrIE1vbm8gVG8gU3RlcmVvIikpCj4gKwkJaTJzLT5t b25vX3RvX3N0ZXJlb1tJMlNfUlhfUEFUSF0gPSB2YWx1ZTsKPiArCWVsc2UgaWYgKHN0cnN0cihr Y29udHJvbC0+aWQubmFtZSwgIlBsYXliYWNrIEZJRk8gVGhyZXNob2xkIikpCj4gKwkJaTJzLT5y eF9maWZvX3RoID0gdmFsdWU7Cj4gKwllbHNlIGlmIChzdHJzdHIoa2NvbnRyb2wtPmlkLm5hbWUs ICJCQ0xLIFJhdGlvIikpCj4gKwkJaTJzLT5iY2xrX3JhdGlvID0gdmFsdWU7CgpJJ20gcHJldHR5 IHN1cmUgdGhhdCBjaGVja3BhdGNoIHNob3VsZCBjb21wbGFpbiBhYm91dCB0aGUgbWlzc2luZwpi cmFja2V0cywgdGhleSBzaG91bGQgbWFrZSBjb2RlJ3MgaW5kZW50YXRpb24gdW5pZm9ybSBhbmQg dGh1cyBlYXNpZXIgdG8KcmVhZC4gU2FtZSBmb3IgYWxsIG90aGVyIG9jY3VycmVuY2VzIGluIHRo ZSBjb2RlLgoKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3QgY2hhciAqIGNv bnN0IHRlZ3JhMjEwX2kyc19mb3JtYXRfdGV4dFtdID0gewo+ICsJIk5vbmUiLAo+ICsJIjE2IiwK PiArCSIzMiIsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3QgaW50IHRlZ3JhMjEwX2NpZl9mbXRb XSA9IHsKPiArCTAsCj4gKwlURUdSQV9BQ0lGX0JJVFNfMTYsCj4gKwlURUdSQV9BQ0lGX0JJVFNf MzIsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3QgaW50IHRlZ3JhMjEwX2kyc19iaXRfZm10W10g PSB7Cj4gKwkwLAo+ICsJSTJTX0JJVFNfMTYsCj4gKwlJMlNfQklUU18zMiwKPiArfTsKPiArCj4g K3N0YXRpYyBjb25zdCBpbnQgdGVncmEyMTBfaTJzX3NhbXBsZV9zaXplW10gPSB7Cj4gKwkwLAo+ ICsJMTYsCj4gKwkzMiwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0g dGVncmEyMTBfaTJzX2Zvcm1hdF9lbnVtID0KPiArCVNPQ19FTlVNX1NJTkdMRSgwLCAwLCBBUlJB WV9TSVpFKHRlZ3JhMjEwX2kyc19mb3JtYXRfdGV4dCksCj4gKwkJCXRlZ3JhMjEwX2kyc19mb3Jt YXRfdGV4dCk7Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3JhMjEwX2kyc19zZXRfdGltaW5nX3BhcmFt cyhzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkJICB1bnNpZ25lZCBpbnQgc2FtcGxlX3NpemUs Cj4gKwkJCQkJICB1bnNpZ25lZCBpbnQgc3JhdGUsCj4gKwkJCQkJICB1bnNpZ25lZCBpbnQgY2hh bm5lbHMpCj4gK3sKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmkycyA9IGRldl9nZXRfZHJ2ZGF0 YShkZXYpOwo+ICsJdW5zaWduZWQgaW50IHZhbCwgYml0X2NvdW50LCBiY2xrX3JhdGUsIG51bV9i Y2xrID0gc2FtcGxlX3NpemU7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmIChpMnMtPmJjbGtfcmF0 aW8pCj4gKwkJbnVtX2JjbGsgKj0gaTJzLT5iY2xrX3JhdGlvOwo+ICsKPiArCWlmIChpMnMtPmRh aV9mbXQgPT0gU05EX1NPQ19EQUlGTVRfUklHSFRfSikKPiArCQl0ZWdyYTIxMF9pMnNfc2V0X2Rh dGFfb2Zmc2V0KGkycywgbnVtX2JjbGsgLSBzYW1wbGVfc2l6ZSk7Cj4gKwo+ICsJLyogSTJTIGJp dCBjbG9jayByYXRlICovCj4gKwliY2xrX3JhdGUgPSBzcmF0ZSAqIGNoYW5uZWxzICogbnVtX2Jj bGs7Cj4gKwo+ICsJcmV0ID0gdGVncmEyMTBfaTJzX3NldF9jbG9ja19yYXRlKGRldiwgYmNsa19y YXRlKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGRldiwgImNhbid0IHNldCBJMlMgYml0 IGNsb2NrIHJhdGUgJXUsIGVycjogJWRcbiIsCj4gKwkJCWJjbGtfcmF0ZSwgcmV0KTsKPiArCQly ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJlZ21hcF9yZWFkKGkycy0+cmVnbWFwLCBURUdSQTIx MF9JMlNfQ1RSTCwgJnZhbCk7Cj4gKwo+ICsJLyoKPiArCSAqIEZvciBMUkNLIG1vZGUsIGNoYW5u ZWwgYml0IGNvdW50IGRlcGVuZHMgb24gbnVtYmVyIG9mIGJpdCBjbG9ja3MKPiArCSAqIG9uIHRo ZSBsZWZ0IGNoYW5uZWwsIHdoZXJlIGFzIGZvciBGU1lOQyBtb2RlIGJpdCBjb3VudCBkZXBlbmRz IG9uCj4gKwkgKiB0aGUgbnVtYmVyIG9mIGJpdCBjbG9ja3MgaW4gYm90aCBsZWZ0IGFuZCByaWdo dCBjaGFubmVscyBmb3IgRFNQCj4gKwkgKiBtb2RlIG9yIHRoZSBudW1iZXIgb2YgYml0IGNsb2Nr cyBpbiBvbmUgVERNIGZyYW1lLgo+ICsJICoKPiArCSAqLwo+ICsJc3dpdGNoICh2YWwgJiBJMlNf Q1RSTF9GUkFNRV9GTVRfTUFTSykgewo+ICsJY2FzZSBJMlNfQ1RSTF9GUkFNRV9GTVRfTFJDS19N T0RFOgo+ICsJCWJpdF9jb3VudCA9IChiY2xrX3JhdGUgLyAoc3JhdGUgKiAyKSkgLSAxOwo+ICsJ CWJyZWFrOwo+ICsJY2FzZSBJMlNfQ1RSTF9GUkFNRV9GTVRfRlNZTkNfTU9ERToKPiArCQliaXRf Y291bnQgPSAoYmNsa19yYXRlIC8gc3JhdGUpIC0gMTsKPiArCj4gKwkJdGVncmEyMTBfaTJzX3Nl dF9zbG90X2N0cmwoaTJzLT5yZWdtYXAsIGNoYW5uZWxzLAo+ICsJCQkJCSAgIGkycy0+dHhfbWFz aywgaTJzLT5yeF9tYXNrKTsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJZGV2X2Vycihk ZXYsICJpbnZhbGlkIEkyUyBtb2RlXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiAr Cj4gKwlpZiAoYml0X2NvdW50ID4gSTJTX1RJTUlOR19DSF9CSVRfQ05UX01BU0spIHsKPiArCQlk ZXZfZXJyKGRldiwgImludmFsaWQgY2hhbm5lbCBiaXQgY291bnQgJXVcbiIsIGJpdF9jb3VudCk7 Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmVnbWFwX3dyaXRlKGkycy0+cmVn bWFwLCBURUdSQTIxMF9JMlNfVElNSU5HLAo+ICsJCSAgICAgYml0X2NvdW50IDw8IEkyU19USU1J TkdfQ0hfQklUX0NOVF9TSElGVCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgdGVncmEyMTBfaTJzX2h3X3BhcmFtcyhzdHJ1Y3Qgc25kX3BjbV9zdWJzdHJlYW0gKnN1 YnN0cmVhbSwKPiArCQkJCSAgc3RydWN0IHNuZF9wY21faHdfcGFyYW1zICpwYXJhbXMsCj4gKwkJ CQkgIHN0cnVjdCBzbmRfc29jX2RhaSAqZGFpKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYg PSBkYWktPmRldjsKPiArCXN0cnVjdCB0ZWdyYTIxMF9pMnMgKmkycyA9IHNuZF9zb2NfZGFpX2dl dF9kcnZkYXRhKGRhaSk7Cj4gKwl1bnNpZ25lZCBpbnQgc2FtcGxlX3NpemUsIGNoYW5uZWxzLCBz cmF0ZSwgdmFsLCByZWcsIHBhdGg7Cj4gKwlzdHJ1Y3QgdGVncmFfY2lmX2NvbmYgY2lmX2NvbmY7 Cj4gKwlpbnQgbWF4X3RoOwo+ICsKPiArCW1lbXNldCgmY2lmX2NvbmYsIDAsIHNpemVvZihzdHJ1 Y3QgdGVncmFfY2lmX2NvbmYpKTsKPiArCj4gKwljaGFubmVscyA9IHBhcmFtc19jaGFubmVscyhw YXJhbXMpOwo+ICsJaWYgKGNoYW5uZWxzIDwgMSkgewo+ICsJCWRldl9lcnIoZGV2LCAiaW52YWxp ZCAlZCBjaGFubmVsIGNvbmZpZ3VyYXRpb25cbiIsIGNoYW5uZWxzKTsKPiArCQlyZXR1cm4gLUVJ TlZBTDsKPiArCX0KPiArCj4gKwljaWZfY29uZi5hdWRpb19jaCA9IGNoYW5uZWxzOwo+ICsJY2lm X2NvbmYuY2xpZW50X2NoID0gY2hhbm5lbHM7Cj4gKwo+ICsJc3dpdGNoIChwYXJhbXNfZm9ybWF0 KHBhcmFtcykpIHsKPiArCWNhc2UgU05EUlZfUENNX0ZPUk1BVF9TODoKPiArCQl2YWwgPSBJMlNf QklUU184Owo+ICsJCXNhbXBsZV9zaXplID0gODsKPiArCQljaWZfY29uZi5hdWRpb19iaXRzID0g VEVHUkFfQUNJRl9CSVRTXzg7Cj4gKwkJY2lmX2NvbmYuY2xpZW50X2JpdHMgPSBURUdSQV9BQ0lG X0JJVFNfODsKPiArCQlicmVhazsKPiArCWNhc2UgU05EUlZfUENNX0ZPUk1BVF9TMTZfTEU6Cj4g KwkJdmFsID0gSTJTX0JJVFNfMTY7Cj4gKwkJc2FtcGxlX3NpemUgPSAxNjsKPiArCQljaWZfY29u Zi5hdWRpb19iaXRzID0gVEVHUkFfQUNJRl9CSVRTXzE2Owo+ICsJCWNpZl9jb25mLmNsaWVudF9i aXRzID0gVEVHUkFfQUNJRl9CSVRTXzE2Owo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTTkRSVl9QQ01f Rk9STUFUX1MzMl9MRToKPiArCQl2YWwgPSBJMlNfQklUU18zMjsKPiArCQlzYW1wbGVfc2l6ZSA9 IDMyOwo+ICsJCWNpZl9jb25mLmF1ZGlvX2JpdHMgPSBURUdSQV9BQ0lGX0JJVFNfMzI7Cj4gKwkJ Y2lmX2NvbmYuY2xpZW50X2JpdHMgPSBURUdSQV9BQ0lGX0JJVFNfMzI7Cj4gKwkJYnJlYWs7Cj4g KwlkZWZhdWx0Ogo+ICsJCWRldl9lcnIoZGV2LCAidW5zdXBwb3J0ZWQgZm9ybWF0IVxuIik7Cj4g KwkJcmV0dXJuIC1FTk9UU1VQUDsKPiArCX0KPiArCj4gKwlpZiAoaTJzLT5jbGllbnRfZm10X292 ZXJyaWRlKSB7Cj4gKwkJdmFsID0gdGVncmEyMTBfaTJzX2JpdF9mbXRbaTJzLT5jbGllbnRfZm10 X292ZXJyaWRlXTsKPiArCQlzYW1wbGVfc2l6ZSA9Cj4gKwkJCXRlZ3JhMjEwX2kyc19zYW1wbGVf c2l6ZVtpMnMtPmNsaWVudF9mbXRfb3ZlcnJpZGVdOwo+ICsJCWNpZl9jb25mLmNsaWVudF9iaXRz ID0KPiArCQkJdGVncmEyMTBfY2lmX2ZtdFtpMnMtPmNsaWVudF9mbXRfb3ZlcnJpZGVdOwo+ICsJ fQo+ICsKPiArCS8qIFByb2dyYW0gc2FtcGxlIHNpemUgKi8KPiArCXJlZ21hcF91cGRhdGVfYml0 cyhpMnMtPnJlZ21hcCwgVEVHUkEyMTBfSTJTX0NUUkwsCj4gKwkJCSAgIEkyU19DVFJMX0JJVF9T SVpFX01BU0ssIHZhbCk7Cj4gKwo+ICsJc3JhdGUgPSBwYXJhbXNfcmF0ZShwYXJhbXMpOwo+ICsK PiArCS8qIE92ZXJyaWRlIHJhdGUsIGNoYW5uZWwgYW5kIGF1ZGlvIGJpdCBwYXJhbXMgYXMgYXBw bGljYWJsZSAqLwo+ICsJaWYgKGkycy0+c3JhdGVfb3ZlcnJpZGUpCj4gKwkJc3JhdGUgPSBpMnMt PnNyYXRlX292ZXJyaWRlOwo+ICsKPiArCS8qCj4gKwkgKiBGb3IgcGxheWJhY2sgSTJTIFJYLUNJ RiBhbmQgZm9yIGNhcHR1cmUgVFgtQ0lGIGlzIHVzZWQuCj4gKwkgKiBXaXRoIHJlZmVyZW5jZSB0 byBBSFVCLCBmb3IgSTJTLCBTTkRSVl9QQ01fU1RSRUFNX0NBUFRVUkUgc3RyZWFtIGlzCj4gKwkg KiBhY3R1YWxseSBmb3IgcGxheWJhY2suCj4gKwkgKi8KPiArCXBhdGggPSAoc3Vic3RyZWFtLT5z dHJlYW0gPT0gU05EUlZfUENNX1NUUkVBTV9DQVBUVVJFKSA/Cj4gKwkgICAgICAgSTJTX1JYX1BB VEggOiBJMlNfVFhfUEFUSDsKPiArCj4gKwlpZiAoaTJzLT5hdWRpb19jaF9vdmVycmlkZVtwYXRo XSkKPiArCQljaWZfY29uZi5hdWRpb19jaCA9IGkycy0+YXVkaW9fY2hfb3ZlcnJpZGVbcGF0aF07 Cj4gKwo+ICsJaWYgKGkycy0+Y2xpZW50X2NoX292ZXJyaWRlKQo+ICsJCWNpZl9jb25mLmNsaWVu dF9jaCA9IGkycy0+Y2xpZW50X2NoX292ZXJyaWRlOwo+ICsKPiArCWlmIChpMnMtPmF1ZGlvX2Zt dF9vdmVycmlkZVtwYXRoXSkKPiArCQljaWZfY29uZi5hdWRpb19iaXRzID0KPiArCQkJdGVncmEy MTBfY2lmX2ZtdFtpMnMtPmF1ZGlvX2ZtdF9vdmVycmlkZVtwYXRoXV07Cj4gKwo+ICsJaWYgKHN1 YnN0cmVhbS0+c3RyZWFtID09IFNORFJWX1BDTV9TVFJFQU1fQ0FQVFVSRSkgewo+ICsJCXJlZyA9 IFRFR1JBMjEwX0kyU19SWF9DSUZfQ1RSTDsKPiArCj4gKwkJLyogRklGTyB0aHJlc2hvbGQgaW4g dGVybXMgb2YgZnJhbWVzICovCj4gKwkJbWF4X3RoID0gKEkyU19SWF9GSUZPX0RFUFRIIC8gY2lm X2NvbmYuYXVkaW9fY2gpIC0gMTsKPiArCQlpZiAobWF4X3RoIDwgMCkKPiArCQkJcmV0dXJuIC1F SU5WQUw7Cj4gKwo+ICsJCWlmIChpMnMtPnJ4X2ZpZm9fdGggPiBtYXhfdGgpCj4gKwkJCWkycy0+ cnhfZmlmb190aCA9IG1heF90aDsKPiArCj4gKwkJY2lmX2NvbmYudGhyZXNob2xkID0gaTJzLT5y eF9maWZvX3RoOwo+ICsJfSBlbHNlCj4gKwkJcmVnID0gVEVHUkEyMTBfSTJTX1RYX0NJRl9DVFJM Owo+ICsKPiArCWNpZl9jb25mLm1vbm9fY29udiA9IGkycy0+bW9ub190b19zdGVyZW9bcGF0aF07 Cj4gKwljaWZfY29uZi5zdGVyZW9fY29udiA9IGkycy0+c3RlcmVvX3RvX21vbm9bcGF0aF07Cj4g Kwo+ICsJdGVncmFfc2V0X2NpZihpMnMtPnJlZ21hcCwgcmVnLCAmY2lmX2NvbmYpOwo+ICsKPiAr CXJldHVybiB0ZWdyYTIxMF9pMnNfc2V0X3RpbWluZ19wYXJhbXMoZGV2LCBzYW1wbGVfc2l6ZSwg c3JhdGUsCj4gKwkJCQkJICAgICAgY2lmX2NvbmYuY2xpZW50X2NoKTsKPiArfQo+ICsKPiArc3Rh dGljIHN0cnVjdCBzbmRfc29jX2RhaV9vcHMgdGVncmEyMTBfaTJzX2RhaV9vcHMgPSB7Cgpjb25z dD8KCj4gKwkuc2V0X2ZtdAk9IHRlZ3JhMjEwX2kyc19zZXRfZm10LAo+ICsJLmh3X3BhcmFtcwk9 IHRlZ3JhMjEwX2kyc19od19wYXJhbXMsCj4gKwkuc2V0X2JjbGtfcmF0aW8JPSB0ZWdyYTIxMF9p MnNfc2V0X2RhaV9iY2xrX3JhdGlvLAo+ICsJLnNldF90ZG1fc2xvdAk9IHRlZ3JhMjEwX2kyc19z ZXRfdGRtX3Nsb3QsCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBUaHJlZSBEQUlzIGFyZSBleHBvc2Vk Cj4gKyAqIDEuICJDSUYiIERBSSBmb3IgY29ubmVjdGluZyB3aXRoIFhCQVIKPiArICogMi4gIkRB UCIgREFJIGZvciBjb25uZWN0aW5nIHdpdGggQ09ERUMKPiArICogMy4gIkRVTU1ZIiBjYW4gYmUg dXNlZCB3aGVuIG5vIGV4dGVybmFsIGNvZGVjIGNvbm5lY3Rpb24gaXMKPiArICogICAgYXZhaWxh YmxlLiBJbiBzdWNoIGNhc2UgIkRBUCIgaXMgY29ubmVjdGVkIHdpdGggIkRVTU1ZIi4KPiArICog T3JkZXIgb2YgdGhlc2UgREFJcyBzaG91bGQgbm90IGJlIGNoYW5nZWQsIHNpbmNlIERBSSBsaW5r cyBpbiBEVCByZWZlcgo+ICsgKiB0byB0aGVzZSBEQUlzIGRlcGVuZGluZyBvbiB0aGUgaW5kZXgu Cj4gKyAqLwo+ICtzdGF0aWMgc3RydWN0IHNuZF9zb2NfZGFpX2RyaXZlciB0ZWdyYTIxMF9pMnNf ZGFpc1tdID0gewo+ICsJewo+ICsJCS5uYW1lID0gIkNJRiIsCj4gKwkJLnBsYXliYWNrID0gewo+ ICsJCQkuc3RyZWFtX25hbWUgPSAiQ0lGIFJlY2VpdmUiLAo+ICsJCQkuY2hhbm5lbHNfbWluID0g MSwKPiArCQkJLmNoYW5uZWxzX21heCA9IDE2LAo+ICsJCQkucmF0ZXMgPSBTTkRSVl9QQ01fUkFU RV84MDAwXzE5MjAwMCwKPiArCQkJLmZvcm1hdHMgPSBTTkRSVl9QQ01fRk1UQklUX1M4IHwKPiAr CQkJCVNORFJWX1BDTV9GTVRCSVRfUzE2X0xFIHwKPiArCQkJCVNORFJWX1BDTV9GTVRCSVRfUzMy X0xFLAo+ICsJCX0sCj4gKwkJLmNhcHR1cmUgPSB7Cj4gKwkJCS5zdHJlYW1fbmFtZSA9ICJDSUYg VHJhbnNtaXQiLAo+ICsJCQkuY2hhbm5lbHNfbWluID0gMSwKPiArCQkJLmNoYW5uZWxzX21heCA9 IDE2LAo+ICsJCQkucmF0ZXMgPSBTTkRSVl9QQ01fUkFURV84MDAwXzE5MjAwMCwKPiArCQkJLmZv cm1hdHMgPSBTTkRSVl9QQ01fRk1UQklUX1M4IHwKPiArCQkJCVNORFJWX1BDTV9GTVRCSVRfUzE2 X0xFIHwKPiArCQkJCVNORFJWX1BDTV9GTVRCSVRfUzMyX0xFLAo+ICsJCX0sCj4gKwl9LAo+ICsJ ewo+ICsJCS5uYW1lID0gIkRBUCIsCj4gKwkJLnBsYXliYWNrID0gewo+ICsJCQkuc3RyZWFtX25h bWUgPSAiREFQIFJlY2VpdmUiLAo+ICsJCQkuY2hhbm5lbHNfbWluID0gMSwKPiArCQkJLmNoYW5u ZWxzX21heCA9IDE2LAo+ICsJCQkucmF0ZXMgPSBTTkRSVl9QQ01fUkFURV84MDAwXzE5MjAwMCwK PiArCQkJLmZvcm1hdHMgPSBTTkRSVl9QQ01fRk1UQklUX1M4IHwKPiArCQkJCVNORFJWX1BDTV9G TVRCSVRfUzE2X0xFIHwKPiArCQkJCVNORFJWX1BDTV9GTVRCSVRfUzMyX0xFLAo+ICsJCX0sCj4g KwkJLmNhcHR1cmUgPSB7Cj4gKwkJCS5zdHJlYW1fbmFtZSA9ICJEQVAgVHJhbnNtaXQiLAo+ICsJ CQkuY2hhbm5lbHNfbWluID0gMSwKPiArCQkJLmNoYW5uZWxzX21heCA9IDE2LAo+ICsJCQkucmF0 ZXMgPSBTTkRSVl9QQ01fUkFURV84MDAwXzE5MjAwMCwKPiArCQkJLmZvcm1hdHMgPSBTTkRSVl9Q Q01fRk1UQklUX1M4IHwKPiArCQkJCVNORFJWX1BDTV9GTVRCSVRfUzE2X0xFIHwKPiArCQkJCVNO RFJWX1BDTV9GTVRCSVRfUzMyX0xFLAo+ICsJCX0sCj4gKwkJLm9wcyA9ICZ0ZWdyYTIxMF9pMnNf ZGFpX29wcywKPiArCQkuc3ltbWV0cmljX3JhdGVzID0gMSwKPiArCX0sCj4gKwl7Cj4gKwkJLm5h bWUgPSAiRFVNTVkiLAo+ICsJCS5wbGF5YmFjayA9IHsKPiArCQkJLnN0cmVhbV9uYW1lID0gIkR1 bW15IFBsYXliYWNrIiwKPiArCQkJLmNoYW5uZWxzX21pbiA9IDEsCj4gKwkJCS5jaGFubmVsc19t YXggPSAxNiwKPiArCQkJLnJhdGVzID0gU05EUlZfUENNX1JBVEVfODAwMF8xOTIwMDAsCj4gKwkJ CS5mb3JtYXRzID0gU05EUlZfUENNX0ZNVEJJVF9TOCB8Cj4gKwkJCQlTTkRSVl9QQ01fRk1UQklU X1MxNl9MRSB8Cj4gKwkJCQlTTkRSVl9QQ01fRk1UQklUX1MzMl9MRSwKPiArCQl9LAo+ICsJCS5j YXB0dXJlID0gewo+ICsJCQkuc3RyZWFtX25hbWUgPSAiRHVtbXkgQ2FwdHVyZSIsCj4gKwkJCS5j aGFubmVsc19taW4gPSAxLAo+ICsJCQkuY2hhbm5lbHNfbWF4ID0gMTYsCj4gKwkJCS5yYXRlcyA9 IFNORFJWX1BDTV9SQVRFXzgwMDBfMTkyMDAwLAo+ICsJCQkuZm9ybWF0cyA9IFNORFJWX1BDTV9G TVRCSVRfUzggfAo+ICsJCQkJU05EUlZfUENNX0ZNVEJJVF9TMTZfTEUgfAo+ICsJCQkJU05EUlZf UENNX0ZNVEJJVF9TMzJfTEUsCj4gKwkJfSwKPiArCX0sCj4gK307Cj4gKwo+ICtzdGF0aWMgY29u c3QgY2hhciAqIGNvbnN0IHRlZ3JhMjEwX2kyc19zdGVyZW9fY29udl90ZXh0W10gPSB7Cj4gKwki Q0gwIiwgIkNIMSIsICJBVkciLAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IGNoYXIgKiBjb25z dCB0ZWdyYTIxMF9pMnNfbW9ub19jb252X3RleHRbXSA9IHsKPiArCSJaRVJPIiwgIkNPUFkiLAo+ ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBzb2NfZW51bSB0ZWdyYTIxMF9pMnNfbW9u b19jb252X2VudW0gPQo+ICsJU09DX0VOVU1fU0lOR0xFKDAsIDAsIEFSUkFZX1NJWkUodGVncmEy MTBfaTJzX21vbm9fY29udl90ZXh0KSwKPiArCQkJdGVncmEyMTBfaTJzX21vbm9fY29udl90ZXh0 KTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gdGVncmEyMTBfaTJzX3N0ZXJl b19jb252X2VudW0gPQo+ICsJU09DX0VOVU1fU0lOR0xFKDAsIDAsIEFSUkFZX1NJWkUodGVncmEy MTBfaTJzX3N0ZXJlb19jb252X3RleHQpLAo+ICsJCQl0ZWdyYTIxMF9pMnNfc3RlcmVvX2NvbnZf dGV4dCk7Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgdGVncmEy MTBfaTJzX2NvbnRyb2xzW10gPSB7Cj4gKwlTT0NfU0lOR0xFX0VYVCgiTG9vcGJhY2siLCAwLCAw LCAxLCAwLCB0ZWdyYTIxMF9pMnNfZ2V0X2NvbnRyb2wsCj4gKwkJICAgICAgIHRlZ3JhMjEwX2ky c19wdXRfY29udHJvbCksCj4gKwlTT0NfU0lOR0xFX0VYVCgiRlNZTkMgV2lkdGgiLCAwLCAwLCAy NTUsIDAsIHRlZ3JhMjEwX2kyc19nZXRfY29udHJvbCwKPiArCQkgICAgICAgdGVncmEyMTBfaTJz X3B1dF9jb250cm9sKSwKPiArCVNPQ19TSU5HTEVfRVhUKCJTYW1wbGUgUmF0ZSIsIDAsIDAsIDE5 MjAwMCwgMCwgdGVncmEyMTBfaTJzX2dldF9jb250cm9sLAo+ICsJCSAgICAgICB0ZWdyYTIxMF9p MnNfcHV0X2NvbnRyb2wpLAo+ICsJU09DX0VOVU1fRVhUKCJQbGF5YmFjayBBdWRpbyBCaXQgRm9y bWF0IiwgdGVncmEyMTBfaTJzX2Zvcm1hdF9lbnVtLAo+ICsJCSAgICAgdGVncmEyMTBfaTJzX2dl dF9jb250cm9sLCB0ZWdyYTIxMF9pMnNfcHV0X2NvbnRyb2wpLAo+ICsJU09DX0VOVU1fRVhUKCJD YXB0dXJlIEF1ZGlvIEJpdCBGb3JtYXQiLCB0ZWdyYTIxMF9pMnNfZm9ybWF0X2VudW0sCj4gKwkJ ICAgICB0ZWdyYTIxMF9pMnNfZ2V0X2NvbnRyb2wsIHRlZ3JhMjEwX2kyc19wdXRfY29udHJvbCks Cj4gKwlTT0NfRU5VTV9FWFQoIkNsaWVudCBCaXQgRm9ybWF0IiwgdGVncmEyMTBfaTJzX2Zvcm1h dF9lbnVtLAo+ICsJCSAgICAgdGVncmEyMTBfaTJzX2dldF9jb250cm9sLCB0ZWdyYTIxMF9pMnNf cHV0X2NvbnRyb2wpLAo+ICsJU09DX1NJTkdMRV9FWFQoIlBsYXliYWNrIEF1ZGlvIENoYW5uZWxz IiwgMCwgMCwgMTYsIDAsCj4gKwkJICAgICAgIHRlZ3JhMjEwX2kyc19nZXRfY29udHJvbCwgdGVn cmEyMTBfaTJzX3B1dF9jb250cm9sKSwKPiArCVNPQ19TSU5HTEVfRVhUKCJDYXB0dXJlIEF1ZGlv IENoYW5uZWxzIiwgMCwgMCwgMTYsIDAsCj4gKwkJICAgICAgIHRlZ3JhMjEwX2kyc19nZXRfY29u dHJvbCwgdGVncmEyMTBfaTJzX3B1dF9jb250cm9sKSwKPiArCVNPQ19TSU5HTEVfRVhUKCJDbGll bnQgQ2hhbm5lbHMiLCAwLCAwLCAxNiwgMCwKPiArCQkgICAgICAgdGVncmEyMTBfaTJzX2dldF9j b250cm9sLCB0ZWdyYTIxMF9pMnNfcHV0X2NvbnRyb2wpLAo+ICsJU09DX0VOVU1fRVhUKCJDYXB0 dXJlIFN0ZXJlbyBUbyBNb25vIiwgdGVncmEyMTBfaTJzX3N0ZXJlb19jb252X2VudW0sCj4gKwkJ ICAgICB0ZWdyYTIxMF9pMnNfZ2V0X2NvbnRyb2wsIHRlZ3JhMjEwX2kyc19wdXRfY29udHJvbCks Cj4gKwlTT0NfRU5VTV9FWFQoIkNhcHR1cmUgTW9ubyBUbyBTdGVyZW8iLCB0ZWdyYTIxMF9pMnNf bW9ub19jb252X2VudW0sCj4gKwkJICAgICB0ZWdyYTIxMF9pMnNfZ2V0X2NvbnRyb2wsIHRlZ3Jh MjEwX2kyc19wdXRfY29udHJvbCksCj4gKwlTT0NfRU5VTV9FWFQoIlBsYXliYWNrIFN0ZXJlbyBU byBNb25vIiwgdGVncmEyMTBfaTJzX3N0ZXJlb19jb252X2VudW0sCj4gKwkJICAgICB0ZWdyYTIx MF9pMnNfZ2V0X2NvbnRyb2wsIHRlZ3JhMjEwX2kyc19wdXRfY29udHJvbCksCj4gKwlTT0NfRU5V TV9FWFQoIlBsYXliYWNrIE1vbm8gVG8gU3RlcmVvIiwgdGVncmEyMTBfaTJzX21vbm9fY29udl9l bnVtLAo+ICsJCSAgICAgdGVncmEyMTBfaTJzX2dldF9jb250cm9sLCB0ZWdyYTIxMF9pMnNfcHV0 X2NvbnRyb2wpLAo+ICsJU09DX1NJTkdMRV9FWFQoIlBsYXliYWNrIEZJRk8gVGhyZXNob2xkIiwg MCwgMCwgSTJTX1JYX0ZJRk9fREVQVEggLSAxLAo+ICsJCSAgICAgICAwLCB0ZWdyYTIxMF9pMnNf Z2V0X2NvbnRyb2wsIHRlZ3JhMjEwX2kyc19wdXRfY29udHJvbCksCj4gKwlTT0NfU0lOR0xFX0VY VCgiQkNMSyBSYXRpbyIsIDAsIDAsIElOVF9NQVgsIDAsIHRlZ3JhMjEwX2kyc19nZXRfY29udHJv bCwKPiArCQkgICAgICAgdGVncmEyMTBfaTJzX3B1dF9jb250cm9sKSwKPiArfTsKPiArCj4gK3N0 YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX3NvY19kYXBtX3dpZGdldCB0ZWdyYTIxMF9pMnNfd2lkZ2V0 c1tdID0gewo+ICsJU05EX1NPQ19EQVBNX0FJRl9JTigiQ0lGIFJYIiwgTlVMTCwgMCwgU05EX1NP Q19OT1BNLCAwLCAwKSwKPiArCVNORF9TT0NfREFQTV9BSUZfT1VUKCJDSUYgVFgiLCBOVUxMLCAw LCBTTkRfU09DX05PUE0sIDAsIDApLAo+ICsJU05EX1NPQ19EQVBNX0FJRl9JTl9FKCJEQVAgUlgi LCBOVUxMLCAwLCBURUdSQTIxMF9JMlNfVFhfRU5BQkxFLAo+ICsJCQkgICAgICAwLCAwLCB0ZWdy YTIxMF9pMnNfaW5pdCwgU05EX1NPQ19EQVBNX1BSRV9QTVUpLAo+ICsJU05EX1NPQ19EQVBNX0FJ Rl9PVVRfRSgiREFQIFRYIiwgTlVMTCwgMCwgVEVHUkEyMTBfSTJTX1JYX0VOQUJMRSwKPiArCQkJ ICAgICAgIDAsIDAsIHRlZ3JhMjEwX2kyc19pbml0LCBTTkRfU09DX0RBUE1fUFJFX1BNVSksCj4g KwlTTkRfU09DX0RBUE1fTUlDKCJEdW1teSBJbnB1dCIsIE5VTEwpLAo+ICsJU05EX1NPQ19EQVBN X1NQSygiRHVtbXkgT3V0cHV0IiwgTlVMTCksCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3Ry dWN0IHNuZF9zb2NfZGFwbV9yb3V0ZSB0ZWdyYTIxMF9pMnNfcm91dGVzW10gPSB7Cj4gKwl7ICJD SUYgUlgiLAkgIE5VTEwsICJDSUYgUmVjZWl2ZSIgfSwKPiArCXsgIkRBUCBUWCIsCSAgTlVMTCwg IkNJRiBSWCIgfSwKPiArCXsgIkRBUCBUcmFuc21pdCIsIE5VTEwsICJEQVAgVFgiIH0sCj4gKwo+ ICsJeyAiREFQIFJYIiwJICBOVUxMLCAiREFQIFJlY2VpdmUiIH0sCj4gKwl7ICJDSUYgVFgiLAkg IE5VTEwsICJEQVAgUlgiIH0sCj4gKwl7ICJDSUYgVHJhbnNtaXQiLCBOVUxMLCAiQ0lGIFRYIiB9 LAo+ICsKPiArCXsgIkR1bW15IENhcHR1cmUiLCBOVUxMLCAiRHVtbXkgSW5wdXQiIH0sCj4gKwl7 ICJEdW1teSBPdXRwdXQiLCBOVUxMLCAiRHVtbXkgUGxheWJhY2siIH0sCj4gK307Cj4gKwo+ICtz dGF0aWMgY29uc3Qgc3RydWN0IHNuZF9zb2NfY29tcG9uZW50X2RyaXZlciB0ZWdyYTIxMF9pMnNf Y21wbnQgPSB7Cj4gKwkuZGFwbV93aWRnZXRzID0gdGVncmEyMTBfaTJzX3dpZGdldHMsCj4gKwku bnVtX2RhcG1fd2lkZ2V0cyA9IEFSUkFZX1NJWkUodGVncmEyMTBfaTJzX3dpZGdldHMpLAo+ICsJ LmRhcG1fcm91dGVzID0gdGVncmEyMTBfaTJzX3JvdXRlcywKPiArCS5udW1fZGFwbV9yb3V0ZXMg PSBBUlJBWV9TSVpFKHRlZ3JhMjEwX2kyc19yb3V0ZXMpLAo+ICsJLmNvbnRyb2xzID0gdGVncmEy MTBfaTJzX2NvbnRyb2xzLAo+ICsJLm51bV9jb250cm9scyA9IEFSUkFZX1NJWkUodGVncmEyMTBf aTJzX2NvbnRyb2xzKSwKPiArCS5ub25fbGVnYWN5X2RhaV9uYW1pbmcgPSAxLAo+ICt9Owo+ICsK PiArc3RhdGljIGJvb2wgdGVncmEyMTBfaTJzX3dyX3JlZyhzdHJ1Y3QgZGV2aWNlICpkZXYsIHVu c2lnbmVkIGludCByZWcpCj4gK3sKPiArCXN3aXRjaCAocmVnKSB7Cj4gKwljYXNlIFRFR1JBMjEw X0kyU19SWF9FTkFCTEUgLi4uIFRFR1JBMjEwX0kyU19SWF9TT0ZUX1JFU0VUOgo+ICsJY2FzZSBU RUdSQTIxMF9JMlNfUlhfSU5UX01BU0sgLi4uIFRFR1JBMjEwX0kyU19SWF9DTEtfVFJJTToKPiAr CWNhc2UgVEVHUkEyMTBfSTJTX1RYX0VOQUJMRSAuLi4gVEVHUkEyMTBfSTJTX1RYX1NPRlRfUkVT RVQ6Cj4gKwljYXNlIFRFR1JBMjEwX0kyU19UWF9JTlRfTUFTSyAuLi4gVEVHUkEyMTBfSTJTX1RY X0NMS19UUklNOgo+ICsJY2FzZSBURUdSQTIxMF9JMlNfRU5BQkxFIC4uLiBURUdSQTIxMF9JMlNf Q0c6Cj4gKwljYXNlIFRFR1JBMjEwX0kyU19DVFJMIC4uLiBURUdSQTIxMF9JMlNfQ1lBOgo+ICsJ CXJldHVybiB0cnVlOwo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gZmFsc2U7Cj4gKwl9Owo+ICt9 Cj4gKwo+ICtzdGF0aWMgYm9vbCB0ZWdyYTIxMF9pMnNfcmRfcmVnKHN0cnVjdCBkZXZpY2UgKmRl diwgdW5zaWduZWQgaW50IHJlZykKPiArewo+ICsJaWYgKHRlZ3JhMjEwX2kyc193cl9yZWcoZGV2 LCByZWcpKQo+ICsJCXJldHVybiB0cnVlOwo+ICsKPiArCXN3aXRjaCAocmVnKSB7Cj4gKwljYXNl IFRFR1JBMjEwX0kyU19SWF9TVEFUVVM6Cj4gKwljYXNlIFRFR1JBMjEwX0kyU19SWF9JTlRfU1RB VFVTOgo+ICsJY2FzZSBURUdSQTIxMF9JMlNfUlhfQ0lGX0ZJRk9fU1RBVFVTOgo+ICsJY2FzZSBU RUdSQTIxMF9JMlNfVFhfU1RBVFVTOgo+ICsJY2FzZSBURUdSQTIxMF9JMlNfVFhfSU5UX1NUQVRV UzoKPiArCWNhc2UgVEVHUkEyMTBfSTJTX1RYX0NJRl9GSUZPX1NUQVRVUzoKPiArCWNhc2UgVEVH UkEyMTBfSTJTX1NUQVRVUzoKPiArCWNhc2UgVEVHUkEyMTBfSTJTX0lOVF9TVEFUVVM6Cj4gKwkJ cmV0dXJuIHRydWU7Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiBmYWxzZTsKPiArCX07Cj4gK30K PiArCj4gK3N0YXRpYyBib29sIHRlZ3JhMjEwX2kyc192b2xhdGlsZV9yZWcoc3RydWN0IGRldmlj ZSAqZGV2LCB1bnNpZ25lZCBpbnQgcmVnKQo+ICt7Cj4gKwlzd2l0Y2ggKHJlZykgewo+ICsJY2Fz ZSBURUdSQTIxMF9JMlNfUlhfU1RBVFVTOgo+ICsJY2FzZSBURUdSQTIxMF9JMlNfUlhfSU5UX1NU QVRVUzoKPiArCWNhc2UgVEVHUkEyMTBfSTJTX1JYX0NJRl9GSUZPX1NUQVRVUzoKPiArCWNhc2Ug VEVHUkEyMTBfSTJTX1RYX1NUQVRVUzoKPiArCWNhc2UgVEVHUkEyMTBfSTJTX1RYX0lOVF9TVEFU VVM6Cj4gKwljYXNlIFRFR1JBMjEwX0kyU19UWF9DSUZfRklGT19TVEFUVVM6Cj4gKwljYXNlIFRF R1JBMjEwX0kyU19TVEFUVVM6Cj4gKwljYXNlIFRFR1JBMjEwX0kyU19JTlRfU1RBVFVTOgo+ICsJ Y2FzZSBURUdSQTIxMF9JMlNfUlhfU09GVF9SRVNFVDoKPiArCWNhc2UgVEVHUkEyMTBfSTJTX1RY X1NPRlRfUkVTRVQ6Cj4gKwkJcmV0dXJuIHRydWU7Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiBm YWxzZTsKPiArCX07Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmVnbWFwX2NvbmZp ZyB0ZWdyYTIxMF9pMnNfcmVnbWFwX2NvbmZpZyA9IHsKPiArCS5yZWdfYml0cwkJPSAzMiwKPiAr CS5yZWdfc3RyaWRlCQk9IDQsCj4gKwkudmFsX2JpdHMJCT0gMzIsCj4gKwkubWF4X3JlZ2lzdGVy CQk9IFRFR1JBMjEwX0kyU19DWUEsCj4gKwkud3JpdGVhYmxlX3JlZwkJPSB0ZWdyYTIxMF9pMnNf d3JfcmVnLAo+ICsJLnJlYWRhYmxlX3JlZwkJPSB0ZWdyYTIxMF9pMnNfcmRfcmVnLAo+ICsJLnZv bGF0aWxlX3JlZwkJPSB0ZWdyYTIxMF9pMnNfdm9sYXRpbGVfcmVnLAo+ICsJLnJlZ19kZWZhdWx0 cwkJPSB0ZWdyYTIxMF9pMnNfcmVnX2RlZmF1bHRzLAo+ICsJLm51bV9yZWdfZGVmYXVsdHMJPSBB UlJBWV9TSVpFKHRlZ3JhMjEwX2kyc19yZWdfZGVmYXVsdHMpLAo+ICsJLmNhY2hlX3R5cGUJCT0g UkVHQ0FDSEVfRkxBVCwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNl X2lkIHRlZ3JhMjEwX2kyc19vZl9tYXRjaFtdID0gewo+ICsJeyAuY29tcGF0aWJsZSA9ICJudmlk aWEsdGVncmEyMTAtaTJzIiB9LAo+ICsJe30sCj4gK307Cj4gKwo+ICtzdGF0aWMgaW50IHRlZ3Jh MjEwX2kyc19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1 Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Owo+ICsJc3RydWN0IHRlZ3JhMjEwX2kycyAqaTJz Owo+ICsJdm9pZCBfX2lvbWVtICpyZWdzOwo+ICsJaW50IHJldCA9IDA7CgpQbGVhc2UgZG8gbm90 IGluaXRpYWxpemUgdmFyaWFibGVzIGlmIGl0J3Mgbm90IHJlYWxseSBuZWVkZWQsIHRvIGtlZXAK Y29kZSBjbGVhbmVyLiBTYW1lIGZvciBhbGwgb3RoZXIgb2NjdXJyZW5jZXMgaW4gdGhlIGNvZGUu Cgo+ICsJaTJzID0gZGV2bV9rY2FsbG9jKGRldiwgMSwgc2l6ZW9mKCppMnMpLCBHRlBfS0VSTkVM KTsKPiArCWlmICghaTJzKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWkycy0+cnhfZmlm b190aCA9IERFRkFVTFRfSTJTX1JYX0ZJRk9fVEhSRVNIT0xEOwo+ICsJaTJzLT50eF9tYXNrID0g aTJzLT5yeF9tYXNrID0gREVGQVVMVF9JMlNfU0xPVF9NQVNLOwo+ICsJaTJzLT5sb29wYmFjayA9 IGZhbHNlOwo+ICsKPiArCWRldl9zZXRfZHJ2ZGF0YShkZXYsIGkycyk7Cj4gKwo+ICsJaTJzLT5j bGtfaTJzID0gZGV2bV9jbGtfZ2V0KGRldiwgImkycyIpOwo+ICsJaWYgKElTX0VSUihpMnMtPmNs a19pMnMpKSB7Cj4gKwkJZGV2X2VycihkZXYsICJjYW4ndCByZXRyaWV2ZSBJMlMgYml0IGNsb2Nr XG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUihpMnMtPmNsa19pMnMpOwo+ICsJfQo+ICsKPiArCS8q Cj4gKwkgKiBOb3QgYW4gZXJyb3IsIGFzIHRoaXMgY2xvY2sgaXMgbmVlZGVkIG9ubHkgd2hlbiBz b21lIG90aGVyIEkvTwo+ICsJICogcmVxdWlyZXMgaW5wdXQgY2xvY2sgZnJvbSBjdXJyZW50IEky UyBpbnN0YW5jZSwgd2hpY2ggaXMKPiArCSAqIGNvbmZpZ3VyYWJsZSBmcm9tIERULgo+ICsJICov Cj4gKwlpMnMtPmNsa19zeW5jX2lucHV0ID0gZGV2bV9jbGtfZ2V0KGRldiwgInN5bmNfaW5wdXQi KTsKPiArCWlmIChJU19FUlIoaTJzLT5jbGtfc3luY19pbnB1dCkpCj4gKwkJZGV2X2RiZyhkZXYs ICJjYW4ndCByZXRyaWV2ZSBJMlMgc3luYyBpbnB1dCBjbG9ja1xuIik7Cj4gKwo+ICsJcmVncyA9 IGRldm1fcGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPiArCWlmIChJU19FUlIo cmVncykpCj4gKwkJcmV0dXJuIFBUUl9FUlIocmVncyk7Cj4gKwo+ICsJaTJzLT5yZWdtYXAgPSBk ZXZtX3JlZ21hcF9pbml0X21taW8oZGV2LCByZWdzLAo+ICsJCQkJCSAgICAmdGVncmEyMTBfaTJz X3JlZ21hcF9jb25maWcpOwo+ICsJaWYgKElTX0VSUihpMnMtPnJlZ21hcCkpIHsKPiArCQlkZXZf ZXJyKGRldiwgInJlZ21hcCBpbml0IGZhaWxlZFxuIik7Cj4gKwkJcmV0dXJuIFBUUl9FUlIoaTJz LT5yZWdtYXApOwo+ICsJfQo+ICsKPiArCXJlZ2NhY2hlX2NhY2hlX29ubHkoaTJzLT5yZWdtYXAs IHRydWUpOwo+ICsKPiArCXJldCA9IGRldm1fc25kX3NvY19yZWdpc3Rlcl9jb21wb25lbnQoZGV2 LCAmdGVncmEyMTBfaTJzX2NtcG50LAo+ICsJCQkJCSAgICAgIHRlZ3JhMjEwX2kyc19kYWlzLAo+ ICsJCQkJCSAgICAgIEFSUkFZX1NJWkUodGVncmEyMTBfaTJzX2RhaXMpKTsKPiArCWlmIChyZXQg IT0gMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiY2FuJ3QgcmVnaXN0ZXIgSTJTIGNvbXBvbmVudCwg ZXJyOiAlZFxuIiwgcmV0KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXBtX3J1bnRp bWVfZW5hYmxlKGRldik7CgpFcnJvciBjaGVja2luZz8KCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsK PiArc3RhdGljIGludCB0ZWdyYTIxMF9pMnNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug KnBkZXYpCj4gK3sKPiArCXBtX3J1bnRpbWVfZGlzYWJsZSgmcGRldi0+ZGV2KTsKCj4gKwlpZiAo IXBtX3J1bnRpbWVfc3RhdHVzX3N1c3BlbmRlZCgmcGRldi0+ZGV2KSkKPiArCQl0ZWdyYTIxMF9p MnNfcnVudGltZV9zdXNwZW5kKCZwZGV2LT5kZXYpOwoKVGhpcyBicmVha3MgZGV2aWNlJ3MgUlBN IHJlZmNvdW50aW5nIGlmIGl0IHdhcyBkaXNhYmxlZCBpbiB0aGUgYWN0aXZlCnN0YXRlLiBUaGlz IGNvZGUgc2hvdWxkIGJlIHJlbW92ZWQuIEF0IG1vc3QgeW91IGNvdWxkIHdhcm4gYWJvdXQgdGhl CnVueHBlY3RlZCBSUE0gc3RhdGUgaGVyZSwgYnV0IGl0IHNob3VsZG4ndCBiZSBuZWNlc3Nhcnku Cgo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZGV2X3BtX29w cyB0ZWdyYTIxMF9pMnNfcG1fb3BzID0gewo+ICsJU0VUX1JVTlRJTUVfUE1fT1BTKHRlZ3JhMjEw X2kyc19ydW50aW1lX3N1c3BlbmQsCj4gKwkJCSAgIHRlZ3JhMjEwX2kyc19ydW50aW1lX3Jlc3Vt ZSwgTlVMTCkKPiArCVNFVF9MQVRFX1NZU1RFTV9TTEVFUF9QTV9PUFMocG1fcnVudGltZV9mb3Jj ZV9zdXNwZW5kLAo+ICsJCQkJICAgICBwbV9ydW50aW1lX2ZvcmNlX3Jlc3VtZSkKPiArfTsKPiAr Cj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHRlZ3JhMjEwX2kyc19kcml2ZXIgPSB7 Cj4gKwkuZHJpdmVyID0gewo+ICsJCS5uYW1lID0gRFJWX05BTUUsCgpXaWxsIGJlIG5pY2VyIHRv IHNldCB0aGUgbmFtZSBkaXJlY3RseSBoZXJlLCB0aHVzIHRvIHJlbW92ZSB0aGUgRFJWX05BTUUK bWFjcm8uCgo+ICsJCS5vd25lciA9IFRISVNfTU9EVUxFLAoKTm8gbmVlZCB0byBleHBsaWNpdGx5 IHNldCB0aGUgb3duZXIsIGRyaXZlcnMgY29yZSB0YWtlcyBjYXJlIGFib3V0IGl0LgoKPiArCQku b2ZfbWF0Y2hfdGFibGUgPSB0ZWdyYTIxMF9pMnNfb2ZfbWF0Y2gsCj4gKwkJLnBtID0gJnRlZ3Jh MjEwX2kyc19wbV9vcHMsCj4gKwl9LAo+ICsJLnByb2JlID0gdGVncmEyMTBfaTJzX3Byb2JlLAo+ ICsJLnJlbW92ZSA9IHRlZ3JhMjEwX2kyc19yZW1vdmUsCj4gK307Cj4gK21vZHVsZV9wbGF0Zm9y bV9kcml2ZXIodGVncmEyMTBfaTJzX2RyaXZlcikKPiArCj4gK01PRFVMRV9BVVRIT1IoIlNvbmdo ZWUgQmFlayA8c2JhZWtAbnZpZGlhLmNvbT4iKTsKPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJUZWdy YTIxMCBBU29DIEkyUyBkcml2ZXIiKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwoKPiAr TU9EVUxFX0RFVklDRV9UQUJMRShvZiwgdGVncmEyMTBfaTJzX29mX21hdGNoKTsKCldoYXQgYWJv dXQgdG8gcGxhY2UgTU9EVUxFX0RFVklDRV9UQUJMRSgpIHJpZ2h0IGFmdGVyIHRoZSBkZWZpbml0 aW9uIG9mCnRlZ3JhMjEwX2kyc19vZl9tYXRjaCBsaWtlIGl0J3MgZG9uZSBieSBtb3N0IG9mIHRo ZSBkcml2ZXJzIGluIGtlcm5lbD8KCj4gZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy90ZWdyYS90ZWdy YTIxMF9pMnMuaCBiL3NvdW5kL3NvYy90ZWdyYS90ZWdyYTIxMF9pMnMuaAo+IG5ldyBmaWxlIG1v ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uMTIxZGZmNwo+IC0tLSAvZGV2L251bGwKPiArKysg Yi9zb3VuZC9zb2MvdGVncmEvdGVncmEyMTBfaTJzLmgKPiBAQCAtMCwwICsxLDEzMiBAQAo+ICsv KiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMC1vbmx5ICovCj4gKy8qCj4gKyAqIHRl Z3JhMjEwX2kycy5oIC0gRGVmaW5pdGlvbnMgZm9yIFRlZ3JhMjEwIEkyUyBkcml2ZXIKPiArICoK PiArICogQ29weXJpZ2h0IChjKSAyMDIwIE5WSURJQSBDT1JQT1JBVElPTi4gQWxsIHJpZ2h0cyBy ZXNlcnZlZC4KPiArICoKPiArICovCj4gKwo+ICsjaWZuZGVmIF9fVEVHUkEyMTBfSTJTX0hfXwo+ ICsjZGVmaW5lIF9fVEVHUkEyMTBfSTJTX0hfXwo+ICsKPiArLyogUmVnaXN0ZXIgb2Zmc2V0cyBm cm9tIEkyUypfQkFTRSAqLwo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19SWF9FTkFCTEUJCQkweDAK PiArI2RlZmluZSBURUdSQTIxMF9JMlNfUlhfU09GVF9SRVNFVAkJMHg0Cj4gKyNkZWZpbmUgVEVH UkEyMTBfSTJTX1JYX1NUQVRVUwkJCTB4MGMKPiArI2RlZmluZSBURUdSQTIxMF9JMlNfUlhfSU5U X1NUQVRVUwkJMHgxMAo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19SWF9JTlRfTUFTSwkJMHgxNAo+ ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19SWF9JTlRfU0VUCQkJMHgxOAo+ICsjZGVmaW5lIFRFR1JB MjEwX0kyU19SWF9JTlRfQ0xFQVIJCTB4MWMKPiArI2RlZmluZSBURUdSQTIxMF9JMlNfUlhfQ0lG X0NUUkwJCTB4MjAKPiArI2RlZmluZSBURUdSQTIxMF9JMlNfUlhfQ1RSTAkJCTB4MjQKPiArI2Rl ZmluZSBURUdSQTIxMF9JMlNfUlhfU0xPVF9DVFJMCQkweDI4Cj4gKyNkZWZpbmUgVEVHUkEyMTBf STJTX1JYX0NMS19UUklNCQkweDJjCj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1JYX0NZQQkJCTB4 MzAKPiArI2RlZmluZSBURUdSQTIxMF9JMlNfUlhfQ0lGX0ZJRk9fU1RBVFVTCQkweDM0Cj4gKyNk ZWZpbmUgVEVHUkEyMTBfSTJTX1RYX0VOQUJMRQkJCTB4NDAKPiArI2RlZmluZSBURUdSQTIxMF9J MlNfVFhfU09GVF9SRVNFVAkJMHg0NAo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19UWF9TVEFUVVMJ CQkweDRjCj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1RYX0lOVF9TVEFUVVMJCTB4NTAKPiArI2Rl ZmluZSBURUdSQTIxMF9JMlNfVFhfSU5UX01BU0sJCTB4NTQKPiArI2RlZmluZSBURUdSQTIxMF9J MlNfVFhfSU5UX1NFVAkJCTB4NTgKPiArI2RlZmluZSBURUdSQTIxMF9JMlNfVFhfSU5UX0NMRUFS CQkweDVjCj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1RYX0NJRl9DVFJMCQkweDYwCj4gKyNkZWZp bmUgVEVHUkEyMTBfSTJTX1RYX0NUUkwJCQkweDY0Cj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1RY X1NMT1RfQ1RSTAkJMHg2OAo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19UWF9DTEtfVFJJTQkJMHg2 Ywo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19UWF9DWUEJCQkweDcwCj4gKyNkZWZpbmUgVEVHUkEy MTBfSTJTX1RYX0NJRl9GSUZPX1NUQVRVUwkJMHg3NAo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19F TkFCTEUJCQkweDgwCj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1NPRlRfUkVTRVQJCQkweDg0Cj4g KyNkZWZpbmUgVEVHUkEyMTBfSTJTX0NHCQkJCTB4ODgKPiArI2RlZmluZSBURUdSQTIxMF9JMlNf U1RBVFVTCQkJMHg4Ywo+ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19JTlRfU1RBVFVTCQkJMHg5MAo+ ICsjZGVmaW5lIFRFR1JBMjEwX0kyU19DVFJMCQkJMHhhMAo+ICsjZGVmaW5lIFRFR1JBMjEwX0ky U19USU1JTkcJCQkweGE0Cj4gKyNkZWZpbmUgVEVHUkEyMTBfSTJTX1NMT1RfQ1RSTAkJCTB4YTgK PiArI2RlZmluZSBURUdSQTIxMF9JMlNfQ0xLX1RSSU0JCQkweGFjCj4gKyNkZWZpbmUgVEVHUkEy MTBfSTJTX0NZQQkJCTB4YjAKPiArCj4gKy8qIEJpdCBmaWVsZHMsIHNoaWZ0cyBhbmQgbWFza3Mg Ki8KPiArI2RlZmluZSBJMlNfREFUQV9TSElGVAkJCQk4Cj4gKyNkZWZpbmUgSTJTX0NUUkxfREFU QV9PRkZTRVRfTUFTSwkJKDB4N2ZmIDw8IEkyU19EQVRBX1NISUZUKQo+ICsKPiArI2RlZmluZSBJ MlNfRU5fU0hJRlQJCQkJMAo+ICsjZGVmaW5lIEkyU19FTl9NQVNLCQkJCSgxIDw8IEkyU19FTl9T SElGVCkKPiArI2RlZmluZSBJMlNfRU4JCQkJCSgxIDw8IEkyU19FTl9TSElGVCkKPiArCj4gKyNk ZWZpbmUgSTJTX0ZTWU5DX1dJRFRIX1NISUZUCQkJMjQKPiArI2RlZmluZSBJMlNfQ1RSTF9GU1lO Q19XSURUSF9NQVNLCQkoMHhmZiA8PCBJMlNfRlNZTkNfV0lEVEhfU0hJRlQpCj4gKwo+ICsjZGVm aW5lIEkyU19QT1NfRURHRQkJCQkwCj4gKyNkZWZpbmUgSTJTX05FR19FREdFCQkJCTEKPiArI2Rl ZmluZSBJMlNfRURHRV9TSElGVAkJCQkyMAo+ICsjZGVmaW5lIEkyU19DVFJMX0VER0VfQ1RSTF9N QVNLCQkJKDEgPDwgSTJTX0VER0VfU0hJRlQpCj4gKyNkZWZpbmUgSTJTX0NUUkxfRURHRV9DVFJM X1BPU19FREdFCQkoSTJTX1BPU19FREdFIDw8IEkyU19FREdFX1NISUZUKQo+ICsjZGVmaW5lIEky U19DVFJMX0VER0VfQ1RSTF9ORUdfRURHRQkJKEkyU19ORUdfRURHRSA8PCBJMlNfRURHRV9TSElG VCkKPiArCj4gKyNkZWZpbmUgSTJTX0ZNVF9MUkNLCQkJCTAKPiArI2RlZmluZSBJMlNfRk1UX0ZT WU5DCQkJCTEKPiArI2RlZmluZSBJMlNfRk1UX1NISUZUCQkJCTEyCj4gKyNkZWZpbmUgSTJTX0NU UkxfRlJBTUVfRk1UX01BU0sJCQkoNyA8PCBJMlNfRk1UX1NISUZUKQo+ICsjZGVmaW5lIEkyU19D VFJMX0ZSQU1FX0ZNVF9MUkNLX01PREUJCShJMlNfRk1UX0xSQ0sgPDwgSTJTX0ZNVF9TSElGVCkK PiArI2RlZmluZSBJMlNfQ1RSTF9GUkFNRV9GTVRfRlNZTkNfTU9ERQkJKEkyU19GTVRfRlNZTkMg PDwgSTJTX0ZNVF9TSElGVCkKPiArCj4gKyNkZWZpbmUgSTJTX0NUUkxfTUFTVEVSX0VOX1NISUZU CQkxMAo+ICsjZGVmaW5lIEkyU19DVFJMX01BU1RFUl9FTl9NQVNLCQkJKDEgPDwgSTJTX0NUUkxf TUFTVEVSX0VOX1NISUZUKQo+ICsjZGVmaW5lIEkyU19DVFJMX01BU1RFUl9FTgkJCSgxIDw8IEky U19DVFJMX01BU1RFUl9FTl9TSElGVCkKPiArCj4gKyNkZWZpbmUgSTJTX0NUUkxfTFJDS19QT0xf U0hJRlQJCQk5Cj4gKyNkZWZpbmUgSTJTX0NUUkxfTFJDS19QT0xfTUFTSwkJCSgxIDw8IEkyU19D VFJMX0xSQ0tfUE9MX1NISUZUKQo+ICsjZGVmaW5lIEkyU19DVFJMX0xSQ0tfUE9MX0xPVwkJCSgw IDw8IEkyU19DVFJMX0xSQ0tfUE9MX1NISUZUKQo+ICsjZGVmaW5lIEkyU19DVFJMX0xSQ0tfUE9M X0hJR0gJCQkoMSA8PCBJMlNfQ1RSTF9MUkNLX1BPTF9TSElGVCkKPiArCj4gKyNkZWZpbmUgSTJT X0NUUkxfTFBCS19TSElGVAkJCTgKPiArI2RlZmluZSBJMlNfQ1RSTF9MUEJLX01BU0sJCQkoMSA8 PCBJMlNfQ1RSTF9MUEJLX1NISUZUKQo+ICsjZGVmaW5lIEkyU19DVFJMX0xQQktfRU4JCQkoMSA8 PCBJMlNfQ1RSTF9MUEJLX1NISUZUKQo+ICsKPiArI2RlZmluZSBJMlNfQklUU184CQkJCTEKPiAr I2RlZmluZSBJMlNfQklUU18xNgkJCQkzCj4gKyNkZWZpbmUgSTJTX0JJVFNfMzIJCQkJNwo+ICsj ZGVmaW5lIEkyU19DVFJMX0JJVF9TSVpFX01BU0sJCQkweDcKPiArCj4gKyNkZWZpbmUgSTJTX1RJ TUlOR19DSF9CSVRfQ05UX01BU0sJCTB4N2ZmCj4gKyNkZWZpbmUgSTJTX1RJTUlOR19DSF9CSVRf Q05UX1NISUZUCQkwCj4gKwo+ICsjZGVmaW5lIEkyU19TT0ZUX1JFU0VUX1NISUZUCQkJMAo+ICsj ZGVmaW5lIEkyU19TT0ZUX1JFU0VUX01BU0sJCQkoMSA8PCBJMlNfU09GVF9SRVNFVF9TSElGVCkK PiArI2RlZmluZSBJMlNfU09GVF9SRVNFVF9FTgkJCSgxIDw8IEkyU19TT0ZUX1JFU0VUX1NISUZU KQo+ICsKPiArI2RlZmluZSBJMlNfUlhfRklGT19ERVBUSAkJCTY0Cj4gKyNkZWZpbmUgREVGQVVM VF9JMlNfUlhfRklGT19USFJFU0hPTEQJCTMKPiArCj4gKyNkZWZpbmUgREVGQVVMVF9JMlNfU0xP VF9NQVNLCQkJMHhmZmZmCj4gKwo+ICtlbnVtIHRlZ3JhMjEwX2kyc19wYXRoIHsKPiArCUkyU19S WF9QQVRILAo+ICsJSTJTX1RYX1BBVEgsCj4gKwlJMlNfUEFUSFMsCj4gK307Cj4gKwo+ICtzdHJ1 Y3QgdGVncmEyMTBfaTJzIHsKPiArCXN0cnVjdCBjbGsgKmNsa19pMnM7Cj4gKwlzdHJ1Y3QgY2xr ICpjbGtfc3luY19pbnB1dDsKPiArCXN0cnVjdCByZWdtYXAgKnJlZ21hcDsKPiArCXVuc2lnbmVk IGludCBzdGVyZW9fdG9fbW9ub1tJMlNfUEFUSFNdOwo+ICsJdW5zaWduZWQgaW50IG1vbm9fdG9f c3RlcmVvW0kyU19QQVRIU107Cj4gKwl1bnNpZ25lZCBpbnQgYXVkaW9fY2hfb3ZlcnJpZGVbSTJT X1BBVEhTXTsKPiArCXVuc2lnbmVkIGludCBhdWRpb19mbXRfb3ZlcnJpZGVbSTJTX1BBVEhTXTsK PiArCS8qIENsaWVudCBvdmVycmlkZXMgYXJlIGNvbW1vbiBmb3IgVFggYW5kIFJYIHBhdGhzICov Cj4gKwl1bnNpZ25lZCBpbnQgY2xpZW50X2NoX292ZXJyaWRlOwo+ICsJdW5zaWduZWQgaW50IGNs aWVudF9mbXRfb3ZlcnJpZGU7Cj4gKwl1bnNpZ25lZCBpbnQgc3JhdGVfb3ZlcnJpZGU7Cj4gKwl1 bnNpZ25lZCBpbnQgZGFpX2ZtdDsKPiArCXVuc2lnbmVkIGludCBmc3luY193aWR0aDsKPiArCXVu c2lnbmVkIGludCBiY2xrX3JhdGlvOwo+ICsJdW5zaWduZWQgaW50IHR4X21hc2s7Cj4gKwl1bnNp Z25lZCBpbnQgcnhfbWFzazsKPiArCWludCByeF9maWZvX3RoOwoKQ291bGQgcnhfZmlmb190aCBi ZSBuZWdhdGl2ZT8KCj4gKwlib29sIGxvb3BiYWNrOwo+ICt9Owo+ICsKPiArI2VuZGlmCj4gCgpf X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpBbHNhLWRldmVs IG1haWxpbmcgbGlzdApBbHNhLWRldmVsQGFsc2EtcHJvamVjdC5vcmcKaHR0cHM6Ly9tYWlsbWFu LmFsc2EtcHJvamVjdC5vcmcvbWFpbG1hbi9saXN0aW5mby9hbHNhLWRldmVsCg==