Alsa-devel
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
August 2010
- 127 participants
- 319 discussions
[alsa-devel] [PATCH] ASoC: multi-component: TWL4030: Restore registers on removal
by Peter Ujfalusi 12 Aug '10
by Peter Ujfalusi 12 Aug '10
12 Aug '10
Add back the register restore call, when the codec driver is
removed.
This does not affect normal operation, but it is usefull when
debugging audio through the twl4030 class codecs.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi(a)nokia.com>
---
Hello Liam, Mark
I did missed the removal of the register restore from the module
unload path in multi-comp.
This patchs adds it back.
Peter
sound/soc/codecs/twl4030.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 898430f..c7ee1a4 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2258,6 +2258,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
static int twl4030_soc_remove(struct snd_soc_codec *codec)
{
+ /* Reset registers to their chip default before leaving */
+ twl4030_reset_registers(codec);
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
--
1.7.2
3
2
hi all,
when trying to use the route plugin with an lx6464es soundcard, it seems
that only gain values of 1 work correctly. if i apply a different gain, the
specific channel is silent. when i was trying this on another computer (with
an hdsp and internal hda chip), it was working fine, though ...
the only difference that i found is, that i am aware of is, that the
lx6464es was used with 24bit samples, while the hdsp/hda were using 32bit
samples ...
is it possible that the route plugin has an issue with 24bit samples? or may
there be another reason, explaining this behavior?
thanks, tim
--
tim(a)klingt.org
http://tim.klingt.org
Just what the hell is the experimental tradition?
Morton Feldman
1
0
Hello All,
I am new to alsa interface development. I would like to write
one application which accept *.pcm file as input and give playback of it on
sound device on linux system. My requirement is to set sample rate 44100,
channel 2 and access method is SND_PCM_ACCESS_RW_INTERLEAVED and data length
is 16 bit little endian.
Can any oen guide me how can I start writing application in c
file and which are those APIs which I need to take care and handling of
different error codes. It is very urgent.
Please correct me if I am wrong at anywhere.
-Tejas.
2
1
Hello again
This is a bugfix release. Not all issues have been addressed, but
hopefully the most annoying ones.
1.)
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3678
The "EQ Peaks" mixer element gets skipped since there's not way to
display it correctly at the moment.
Also the mixer now looks for all element channels from 0 up to
SND_MIXER_SCHN_LAST (= 31). Formerly it was only for the first 9 channels.
2.)
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4204
Raymond brought this up but I'm not entirely sure what's the problem
here. Are there actually 5 controls named "Master" on this card?
If so alsamixer-qt4 now appends the element index to the element name
for elements whose name appears more that once. This should happen for
all elements but I could only test it for "Capture" and "Input Source".
Both appear twice on my HDA-Intel onboard card.
Download at:
http://xwmw.org/alsamixer-qt4/
http://sourceforge.net/projects/alsamixer-qt4/files/
Comments are welcome!
Best,
Sebastian H.
2
2
[alsa-devel] [PATCH 1/2] ASoC: Automatically determine control_data for soc-cache users
by Mark Brown 12 Aug '10
by Mark Brown 12 Aug '10
12 Aug '10
Since the provision of a struct device for the CODEC is now mandatory
we can use container_of() to locate the struct i2c_client and struct
spi_device for relevant devices, removing the need to manually set it
in each driver.
A further patch will automate selection of the control type based on
the bus_type of the struct device, further reducing the amount of
driver code required.
Signed-off-by: Mark Brown <broonie(a)opensource.wolfsonmicro.com>
---
sound/soc/soc-cache.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 83cd8ed..b856177 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -584,11 +584,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
#endif
if (io_types[i].i2c_read)
codec->hw_read = io_types[i].i2c_read;
+
+ codec->control_data = container_of(codec->dev,
+ struct i2c_client,
+ dev);
break;
case SND_SOC_SPI:
if (io_types[i].spi_write)
codec->hw_write = io_types[i].spi_write;
+
+ codec->control_data = container_of(codec->dev,
+ struct spi_device,
+ dev);
break;
}
--
1.7.1
1
2
Some of the I2C device names got mangled into the form 0-0x1a rather
than 0-001a as they should be. Also, the WM8580 is at I2C address 0x1b
not 0x1a on SMDK64xx.
Signed-off-by: Mark Brown <broonie(a)opensource.wolfsonmicro.com>
---
sound/soc/atmel/sam9g20_wm8731.c | 2 +-
sound/soc/davinci/davinci-evm.c | 8 ++++----
sound/soc/ep93xx/snappercl15.c | 2 +-
sound/soc/imx/eukrea-tlv320.c | 2 +-
sound/soc/kirkwood/kirkwood-openrd.c | 2 +-
sound/soc/s3c24xx/smdk64xx_wm8580.c | 4 ++--
sound/soc/s6000/s6105-ipcam.c | 2 +-
sound/soc/sh/fsi-ak4642.c | 2 +-
sound/soc/sh/fsi-da7210.c | 2 +-
sound/soc/sh/migor.c | 2 +-
10 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index cf9f6c9..66a6f18 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -184,7 +184,7 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = {
.codec_dai_name = "wm8731-hifi",
.init = at91sam9g20ek_wm8731_init,
.platform_name = "atmel_pcm-audio",
- .codec_name = "wm8731-codec.0-0x1a",
+ .codec_name = "wm8731-codec.0-001a",
.ops = &at91sam9g20ek_ops,
};
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 3d6b5b6..097bbbe 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -162,7 +162,7 @@ static struct snd_soc_dai_link evm_dai = {
.stream_name = "AIC3X",
.cpu_dai_name = "davinci-mcasp-dai.0",
.codec_dai_name = "tlv320aic3x-hifi",
- .codec_name = "tlv320aic3x-codec.0-0x1a",
+ .codec_name = "tlv320aic3x-codec.0-001a",
.platform_name = "davinci-pcm-audio",
.init = evm_aic3x_init,
.ops = &evm_ops,
@@ -175,7 +175,7 @@ static struct snd_soc_dai_link dm365_evm_dai = {
.cpu_dai_name = "davinci-i2s-dai",
.codec_dai_name = "tlv320aic3x-hifi",
.init = evm_aic3x_init,
- .codec_name = "tlv320aic3x-codec.0-0x1a",
+ .codec_name = "tlv320aic3x-codec.0-001a",
.ops = &evm_ops,
#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
.name = "Voice Codec - CQ93VC",
@@ -194,7 +194,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
.cpu_dai_name= "davinci-mcasp-dai.0",
.codec_dai_name = "tlv320aic3x-hifi",
.platform_name ="davinci-pcm-audio",
- .codec_name = "tlv320aic3x-codec.0-0x1a",
+ .codec_name = "tlv320aic3x-codec.0-001a",
.init = evm_aic3x_init,
.ops = &evm_ops,
},
@@ -213,7 +213,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
.stream_name = "AIC3X",
.cpu_dai_name= "davinci-mcasp-dai.0",
.codec_dai_name = "tlv320aic3x-hifi",
- .codec_name = "tlv320aic3x-codec.0-0x1a",
+ .codec_name = "tlv320aic3x-codec.0-001a",
.platform_name = "davinci-pcm-audio",
.init = evm_aic3x_init,
.ops = &evm_ops,
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index 539e839..402d299 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -92,7 +92,7 @@ static struct snd_soc_dai_link snappercl15_dai = {
.stream_name = "AIC23",
.cpu_dai_name = "ep93xx-i2s-dai",
.codec_dai_name = "tlv320aic23-hifi",
- .codec_name = "tlv320aic23-codec.0-0x1a",
+ .codec_name = "tlv320aic23-codec.0-001a",
.platform_name = "ep93xx-pcm-audio",
.init = snappercl15_tlv320aic23_init,
.ops = &snappercl15_ops,
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index ab76cae..807f736 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -81,7 +81,7 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = {
.stream_name = "TLV320AIC23",
.codec_dai = "tlv320aic23-hifi",
.platform_name = "imx-pcm-audio.0",
- .codec_name = "tlv320aic23-codec.0-0x1a",
+ .codec_name = "tlv320aic23-codec.0-001a",
.cpu_dai = "imx-ssi-dai.0",
.ops = &eukrea_tlv320_snd_ops,
};
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 6f9ac42..b375021 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -67,7 +67,7 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
.cpu_dai_name = "kirkwood-i2s-dai",
.platform_name = "kirkwood-pcm-audio",
.codec_dai_name = "cs42l51_hifi",
- .codec_name = "cs42l51-codec.0-0x4a",
+ .codec_name = "cs42l51-codec.0-004a",
.ops = &openrd_client_ops,
},
};
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
index 4ccfe84..9d959a0 100644
--- a/sound/soc/s3c24xx/smdk64xx_wm8580.c
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -226,7 +226,7 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {
.cpu_dai_name = "s3c64xx-i2s-v4-dai",
.codec_dai_name = "wm8580-hifi-playback",
.platform_name = "s3c24xx-pcm-audio",
- .codec_name = "wm8580-codec.0-0x1a",
+ .codec_name = "wm8580-codec.0-001b",
.init = smdk64xx_wm8580_init_paifrx,
.ops = &smdk64xx_ops,
},
@@ -236,7 +236,7 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {
.cpu_dai_name = "s3c64xx-i2s-v4-dai",
.codec_dai_name = "wm8580-hifi-capture",
.platform_name = "s3c24xx-pcm-audio",
- .codec_name = "wm8580-codec.0-0x1a",
+ .codec_name = "wm8580-codec.0-001b",
.init = smdk64xx_wm8580_init_paiftx,
.ops = &smdk64xx_ops,
},
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index dd39467..dff9d39 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -179,7 +179,7 @@ static struct snd_soc_dai_link s6105_dai = {
.cpu_dai_name = "s6000-i2s-dai",
.codec_dai_name = "tlv320aic3x-hifi",
.platform_name = "s6000-pcm-audio",
- .codec_name = "tlv320aic3x-codec.0-0x1a",
+ .codec_name = "tlv320aic3x-codec.0-001a",
.init = s6105_aic3x_init,
.ops = &s6105_ops,
};
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index ff17ff3..9e107a9 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -32,7 +32,7 @@ static struct snd_soc_dai_link fsi_dai_link = {
.cpu_dai_name = "fsia-dai", /* fsi A */
.codec_dai_name = "ak4642-hifi",
.platform_name = "fsi-pcm-audio",
- .codec_name = "ak4642-codec.0-0x12",
+ .codec_name = "ak4642-codec.0-0012",
.init = fsi_ak4642_dai_init,
.ops = NULL,
};
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index e2f6fe5..4f9298f 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -28,7 +28,7 @@ static struct snd_soc_dai_link fsi_da7210_dai = {
.cpu_dai_name = "fsib-dai", /* FSI B */
.codec_dai_name = "da7210-hifi",
.platform_name = "fsi-pcm-audio",
- .codec_name = "da7210-codec.0-0x1a",
+ .codec_name = "da7210-codec.0-001a",
.init = fsi_da7210_init,
};
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index 0dc3a0e..866d78f 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -155,7 +155,7 @@ static struct snd_soc_dai_link migor_dai = {
.cpu_dai_name = "siu-i2s-dai",
.codec_dai_name = "wm8978-hifi",
.platform_name = "siu-pcm-audio",
- .codec_name = "wm8978-codec.0-0x1a",
+ .codec_name = "wm8978-codec.0-001a",
.ops = &migor_dai_ops,
.init = migor_dai_init,
};
--
1.7.1
1
0
Hi all,
I have a problem that I need help from the ALSA experts.
I want to write an alsa shim .ko which creates multiple cards. Let's assume
2 cards. My program calls
snd_card_create() and snd_card_register() two times. I also has 1 PCM for
each of these card.
After install the .ko to the kernal, I see the /proc/asound has card0 and
card1. But the "aplay -l" sees only card0. The snd_card_next() only returns
0 (i.e. 1 card).
What did I miss in my program? The /dev/snd/ has only hwC0D0 and pcmD0C0p.
I am a beginner in ALSA, so I appreciate if you can give the explanation in
detail.
Thank you,
2
1
[alsa-devel] [PATCH 1/4] sound: oss: sh_dac_audio.c removed duplicated #include
by Andrea Gelmini 12 Aug '10
by Andrea Gelmini 12 Aug '10
12 Aug '10
Signed-off-by: Andrea Gelmini <andrea.gelmini(a)gelma.net>
---
sound/oss/sh_dac_audio.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index fdb58eb..479e302 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -15,7 +15,6 @@
#include <linux/linkage.h>
#include <linux/slab.h>
#include <linux/fs.h>
-#include <linux/smp_lock.h>
#include <linux/sound.h>
#include <linux/smp_lock.h>
#include <linux/soundcard.h>
--
1.7.2.1.85.g2d089
2
1
88PM860x codec is used in Marvell development board (Saarb and tavorevb3).
Codec is used as master mode in both of these two boards.
Signed-off-by: Haojian Zhuang <haojian.zhuang(a)marvell.com>
---
sound/soc/pxa/Kconfig | 18 ++++
sound/soc/pxa/Makefile | 4 +
sound/soc/pxa/saarb.c | 208 ++++++++++++++++++++++++++++++++++++++++++++
sound/soc/pxa/tavorevb3.c | 209 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 439 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/pxa/saarb.c
create mode 100644 sound/soc/pxa/tavorevb3.c
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index e30c832..37f191b 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -117,6 +117,24 @@ config SND_PXA2XX_SOC_PALM27X
Say Y if you want to add support for SoC audio on
Palm T|X, T5, E2 or LifeDrive handheld computer.
+config SND_SOC_SAARB
+ tristate "SoC Audio support for Marvell Saarb"
+ depends on SND_PXA2XX_SOC && MACH_SAARB
+ select SND_PXA_SOC_SSP
+ select SND_SOC_88PM860X
+ help
+ Say Y if you want to add support for SoC audio on the
+ Marvell Saarb reference platform.
+
+config SND_SOC_TAVOREVB3
+ tristate "SoC Audio support for Marvell Tavor EVB3"
+ depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
+ select SND_PXA_SOC_SSP
+ select SND_SOC_88PM860X
+ help
+ Say Y if you want to add support for SoC audio on the
+ Marvell Saarb reference platform.
+
config SND_SOC_ZYLONITE
tristate "SoC Audio support for Marvell Zylonite"
depends on SND_PXA2XX_SOC && MACH_ZYLONITE
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index caa03d8..0766016 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -19,6 +19,8 @@ snd-soc-e800-objs := e800_wm9712.o
snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs := em-x270.o
snd-soc-palm27x-objs := palm27x.o
+snd-soc-saarb-objs := saarb.o
+snd-soc-tavorevb3-objs := tavorevb3.o
snd-soc-zylonite-objs := zylonite.o
snd-soc-magician-objs := magician.o
snd-soc-mioa701-objs := mioa701_wm9713.o
@@ -38,6 +40,8 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o
+obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o
+obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
new file mode 100644
index 0000000..4220c28
--- /dev/null
+++ b/sound/soc/pxa/saarb.c
@@ -0,0 +1,208 @@
+/*
+ * saarb.c -- SoC audio for saarb
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang(a)marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/88pm860x-codec.h"
+#include "../../arm/pxa2xx-pcm.h"
+#include "pxa-ssp.h"
+
+static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
+
+static struct platform_device *saarb_snd_device;
+static struct snd_soc_jack hs_jack;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+ {
+ .pin = "Mic Jack",
+ .mask = SND_JACK_MICROPHONE,
+ }, {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+/* saarb machine dapm widgets */
+static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
+ SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
+ SND_SOC_DAPM_SPK("Board Speaker", NULL),
+ SND_SOC_DAPM_MIC("Board Mic 1", NULL),
+ SND_SOC_DAPM_MIC("Board Mic 3", NULL),
+};
+
+/* saarb machine audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Headphone Jack", NULL, "HS1"},
+ {"Headphone Jack", NULL, "HS2"},
+
+ {"Board Speaker", NULL, "LSP"},
+ {"Board Speaker", NULL, "LSN"},
+
+ {"Lineout Out 1", NULL, "LINEOUT1"},
+ {"Lineout Out 2", NULL, "LINEOUT2"},
+
+ {"MIC1P", NULL, "Mic1 Bias"},
+ {"MIC1N", NULL, "Mic1 Bias"},
+ {"Mic1 Bias", NULL, "Board Mic 1"},
+
+ {"MIC2P", NULL, "Mic1 Bias"},
+ {"MIC2N", NULL, "Mic1 Bias"},
+ {"Mic1 Bias", NULL, "Mic Jack"},
+
+ {"MIC3P", NULL, "Mic3 Bias"},
+ {"MIC3N", NULL, "Mic3 Bias"},
+ {"Mic3 Bias", NULL, "Board Mic 3"},
+};
+
+static const struct snd_kcontrol_new pm860x_saarb_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Board Speaker"),
+ SOC_DAPM_PIN_SWITCH("Board Mic 1"),
+ SOC_DAPM_PIN_SWITCH("Board Mic 3"),
+};
+
+static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int width = snd_pcm_format_physical_width(params_format(params));
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
+ PM860X_CLK_DIR_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
+
+ return ret;
+}
+
+static struct snd_soc_ops saarb_i2s_ops = {
+ .hw_params = saarb_i2s_hw_params,
+};
+
+static struct snd_soc_dai_link saarb_dai[] = {
+ {
+ .name = "88PM860x I2S",
+ .stream_name = "I2S Audio",
+ .cpu_dai_name = "pxa-ssp-dai.1",
+ .codec_dai_name = "88pm860x-i2s",
+ .platform_name = "pxa-pcm-audio",
+ .codec_name = "88pm860x-codec",
+ .init = saarb_pm860x_init,
+ .ops = &saarb_i2s_ops,
+ },
+};
+
+static struct snd_soc_card snd_soc_card_saarb = {
+ .name = "Saarb",
+ .dai_link = saarb_dai,
+ .num_links = ARRAY_SIZE(saarb_dai),
+};
+
+static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret;
+
+ ret = snd_soc_add_controls(codec, pm860x_saarb_controls,
+ ARRAY_SIZE(pm860x_saarb_controls));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_new_controls(codec, saarb_dapm_widgets,
+ ARRAY_SIZE(saarb_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_disable_pin(codec, "Board Speaker");
+ snd_soc_dapm_disable_pin(codec, "Board Mic 1");
+ snd_soc_dapm_disable_pin(codec, "Board Mic 3");
+
+ ret = snd_soc_dapm_sync(codec);
+ if (ret < 0)
+ return ret;
+
+ /* Jack detection */
+ ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET
+ | SND_JACK_LINEOUT | SND_JACK_BTN_0, &hs_jack);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+ hs_jack_pins);
+ if (ret < 0)
+ return ret;
+
+ ret = pm860x_hs_detect(codec, &hs_jack, PM860X_DET_MASK);
+ return ret;
+}
+
+static int __init saarb_init(void)
+{
+ int ret;
+
+ if (!machine_is_saarb())
+ return -ENODEV;
+ saarb_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!saarb_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
+
+ ret = platform_device_add(saarb_snd_device);
+ if (ret)
+ platform_device_put(saarb_snd_device);
+
+ return ret;
+}
+
+static void __exit saarb_exit(void)
+{
+ platform_device_unregister(saarb_snd_device);
+}
+
+module_init(saarb_init);
+module_exit(saarb_exit);
+
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang(a)marvell.com>");
+MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
new file mode 100644
index 0000000..d5f8ac9
--- /dev/null
+++ b/sound/soc/pxa/tavorevb3.c
@@ -0,0 +1,209 @@
+/*
+ * tavorevb3.c -- SoC audio for Tavor EVB3
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang(a)marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/88pm860x-codec.h"
+#include "../../arm/pxa2xx-pcm.h"
+#include "pxa-ssp.h"
+
+static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd);
+
+static struct platform_device *evb3_snd_device;
+static struct snd_soc_jack hs_jack;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+ {
+ .pin = "Mic Jack",
+ .mask = SND_JACK_MICROPHONE,
+ }, {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+/* tavorevb3 machine dapm widgets */
+static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
+ SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
+ SND_SOC_DAPM_SPK("Board Speaker", NULL),
+ SND_SOC_DAPM_MIC("Board Mic 1", NULL),
+ SND_SOC_DAPM_MIC("Board Mic 3", NULL),
+};
+
+/* tavorevb3 machine audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Headphone Jack", NULL, "HS1"},
+ {"Headphone Jack", NULL, "HS2"},
+
+ {"Board Speaker", NULL, "LSP"},
+ {"Board Speaker", NULL, "LSN"},
+
+ {"Lineout Out 1", NULL, "LINEOUT1"},
+ {"Lineout Out 2", NULL, "LINEOUT2"},
+
+ {"MIC1P", NULL, "Mic1 Bias"},
+ {"MIC1N", NULL, "Mic1 Bias"},
+ {"Mic1 Bias", NULL, "Board Mic 1"},
+
+ {"MIC2P", NULL, "Mic1 Bias"},
+ {"MIC2N", NULL, "Mic1 Bias"},
+ {"Mic1 Bias", NULL, "Mic Jack"},
+
+ {"MIC3P", NULL, "Mic3 Bias"},
+ {"MIC3N", NULL, "Mic3 Bias"},
+ {"Mic3 Bias", NULL, "Board Mic 3"},
+};
+
+static const struct snd_kcontrol_new pm860x_evb3_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Board Speaker"),
+ SOC_DAPM_PIN_SWITCH("Board Mic 1"),
+ SOC_DAPM_PIN_SWITCH("Board Mic 3"),
+};
+
+static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int width = snd_pcm_format_physical_width(params_format(params));
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
+ PM860X_CLK_DIR_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
+ return ret;
+}
+
+static struct snd_soc_ops evb3_i2s_ops = {
+ .hw_params = evb3_i2s_hw_params,
+};
+
+static struct snd_soc_dai_link evb3_dai[] = {
+ {
+ .name = "88PM860x I2S",
+ .stream_name = "I2S Audio",
+ .cpu_dai_name = "pxa-ssp-dai.1",
+ .codec_dai_name = "88pm860x-i2s",
+ .platform_name = "pxa-pcm-audio",
+ .codec_name = "88pm860x-codec",
+ .init = evb3_pm860x_init,
+ .ops = &evb3_i2s_ops,
+ },
+};
+
+static struct snd_soc_card snd_soc_card_evb3 = {
+ .name = "Tavor EVB3",
+ .dai_link = evb3_dai,
+ .num_links = ARRAY_SIZE(evb3_dai),
+};
+
+static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret;
+
+ ret = snd_soc_add_controls(codec, pm860x_evb3_controls,
+ ARRAY_SIZE(pm860x_evb3_controls));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_new_controls(codec, evb3_dapm_widgets,
+ ARRAY_SIZE(evb3_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_disable_pin(codec, "Board Speaker");
+ snd_soc_dapm_disable_pin(codec, "Board Mic 1");
+ snd_soc_dapm_disable_pin(codec, "Board Mic 3");
+
+ ret = snd_soc_dapm_sync(codec);
+ if (ret < 0)
+ return ret;
+
+ /* Jack detection */
+ ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET
+ | SND_JACK_LINEOUT | SND_JACK_BTN_0, &hs_jack);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+ hs_jack_pins);
+ if (ret < 0)
+ return ret;
+
+ ret = pm860x_hs_detect(codec, &hs_jack, PM860X_DET_MASK);
+ return ret;
+}
+
+static int __init tavorevb3_init(void)
+{
+ int ret;
+
+ if (!machine_is_tavorevb3())
+ return -ENODEV;
+ evb3_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!evb3_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3);
+
+ ret = platform_device_add(evb3_snd_device);
+ if (ret)
+ platform_device_put(evb3_snd_device);
+
+ return ret;
+}
+
+static void __exit tavorevb3_exit(void)
+{
+ platform_device_unregister(evb3_snd_device);
+}
+
+module_init(tavorevb3_init);
+module_exit(tavorevb3_exit);
+
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang(a)marvell.com>");
+MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
+MODULE_LICENSE("GPL");
+
--
1.5.6.5
1
0
Add 88PM860x codec driver. 88PM860x codec supports two interfaces. And it
also supports headset/mic/hook/short detection.
Signed-off-by: Haojian Zhuang <haojian.zhuang(a)marvell.com>
---
sound/soc/codecs/88pm860x-codec.c | 1410 +++++++++++++++++++++++++++++++++++++
sound/soc/codecs/88pm860x-codec.h | 92 +++
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
4 files changed, 1508 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/codecs/88pm860x-codec.c
create mode 100644 sound/soc/codecs/88pm860x-codec.h
diff --git a/sound/soc/codecs/88pm860x-codec.c
b/sound/soc/codecs/88pm860x-codec.c
new file mode 100644
index 0000000..1acb1f1
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -0,0 +1,1410 @@
+/*
+ * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang(a)marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+
+#include "88pm860x-codec.h"
+
+#define MAX_NAME_LEN 20
+#define REG_CACHE_SIZE 0x40
+#define REG_CACHE_BASE 0xb0
+
+/* Status Register 1 (0x01) */
+#define REG_STATUS_1 0x01
+#define MIC_STATUS (1 << 7)
+#define HOOK_STATUS (1 << 6)
+#define HEADSET_STATUS (1 << 5)
+
+/* Mic Detection Register (0x37) */
+#define REG_MIC_DET 0x37
+#define CONTINUOUS_POLLING (3 << 1)
+#define EN_MIC_DET (1 << 0)
+#define MICDET_MASK 0x07
+
+/* Headset Detection Register (0x38) */
+#define REG_HS_DET 0x38
+#define EN_HS_DET (1 << 0)
+
+/* Misc2 Register (0x42) */
+#define REG_MISC2 0x42
+#define AUDIO_PLL (1 << 5)
+#define AUDIO_SECTION_RESET (1 << 4)
+#define AUDIO_SECTION_ON (1 << 3)
+
+/* PCM Interface Register 2 (0xb1) */
+#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */
+#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */
+#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */
+#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */
+#define PCM_GENERAL_I2S 0
+#define PCM_EXACT_I2S 1
+#define PCM_LEFT_I2S 2
+#define PCM_RIGHT_I2S 3
+#define PCM_SHORT_FS 4
+#define PCM_LONG_FS 5
+#define PCM_MODE_MASK 7
+
+/* I2S Interface Register 4 (0xbe) */
+#define I2S_EQU_BYP (1 << 6)
+
+/* DAC Offset Register (0xcb) */
+#define DAC_MUTE (1 << 7)
+
+/* ADC Analog Register 1 (0xd0) */
+#define REG_ADC_ANA_1 0xd0
+#define MIC1BIAS_MASK 0x60
+
+/* Earpiece/Speaker Control Register 2 (0xda) */
+#define REG_EAR2 0xda
+#define RSYNC_CHANGE (1 << 2)
+
+/* Audio Supplies Register 2 (0xdc) */
+#define REG_SUPPLIES2 0xdc
+#define LDO15_READY (1 << 4)
+#define LDO15_EN (1 << 3)
+#define CPUMP_READY (1 << 2)
+#define CPUMP_EN (1 << 1)
+#define AUDIO_EN (1 << 0)
+#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN)
+
+/* Audio Enable Register 1 (0xdd) */
+#define ADC_MOD_RIGHT (1 << 1)
+#define ADC_MOD_LEFT (1 << 0)
+
+/* Audio Enable Register 2 (0xde) */
+#define ADC_LEFT (1 << 5)
+#define ADC_RIGHT (1 << 4)
+
+/* DAC Enable Register 2 (0xe1) */
+#define DAC_LEFT (1 << 5)
+#define DAC_RIGHT (1 << 4)
+#define MODULATOR (1 << 3)
+
+/* Shorts Register (0xeb) */
+#define REG_SHORTS 0xeb
+#define SHORT_LO2 (1 << 6)
+#define SHORT_LO1 (1 << 4)
+#define SHORT_HS2 (1 << 2)
+#define SHORT_HS1 (1 << 0)
+
+enum {
+ FILTER_BYPASS = 0,
+ FILTER_LOW_PASS_1,
+ FILTER_LOW_PASS_2,
+ FILTER_HIGH_PASS_3,
+ FILTER_MAX,
+};
+
+struct pm860x_priv {
+ unsigned int sysclk;
+ unsigned int pcmclk;
+ unsigned int dir;
+ unsigned int filter;
+ struct snd_soc_codec *codec;
+ struct i2c_client *i2c;
+ struct pm860x_chip *chip;
+
+ int irq[4];
+ unsigned char name[4][MAX_NAME_LEN];
+ unsigned char reg_cache[REG_CACHE_SIZE];
+};
+
+/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
+static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1);
+
+/* -9dB to 0db in 3dB steps */
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0);
+
+/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */
+static const unsigned int mic_tlv[] = {
+ TLV_DB_RANGE_HEAD(5),
+ 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0),
+ 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0),
+};
+
+/* {0, 0, 0, -6, 0, 6, 12, 18}dB */
+static const unsigned int aux_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0),
+};
+
+/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */
+static const unsigned int out_tlv[] = {
+ TLV_DB_RANGE_HEAD(4),
+ 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1),
+ 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0),
+};
+
+static const unsigned int st_tlv[] = {
+ TLV_DB_RANGE_HEAD(8),
+ 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0),
+ 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0),
+ 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0),
+ 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0),
+ 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0),
+ 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0),
+};
+
+/* Sidetone Gain = M * 2^(-5-N) */
+struct st_gain {
+ unsigned int db;
+ unsigned int m;
+ unsigned int n;
+};
+
+static struct st_gain st_table[] = {
+ {-12041, 1, 15}, {-11439, 1, 14}, {-11087, 3, 15}, {-10837, 1, 13},
+ {-10643, 5, 15}, {-10485, 3, 14}, {-10351, 7, 15}, {-10235, 1, 12},
+ {-10133, 9, 15}, {-10041, 5, 14}, { -9958, 11, 15}, { -9883, 3, 13},
+ { -9813, 13, 15}, { -9749, 7, 14}, { -9689, 15, 15}, { -9633, 1, 11},
+ { -9580, 17, 15}, { -9531, 9, 14}, { -9484, 19, 15}, { -9439, 5, 13},
+ { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281, 3, 12},
+ { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147, 7, 13},
+ { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031, 1, 10},
+ { -8978, 17, 14}, { -8929, 9, 13}, { -8882, 19, 14}, { -8837, 5, 12},
+ { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679, 3, 11},
+ { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545, 7, 12},
+ { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429, 1, 9},
+ { -8376, 17, 13}, { -8327, 9, 12}, { -8280, 19, 13}, { -8235, 5, 11},
+ { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077, 3, 10},
+ { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943, 7, 11},
+ { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827, 1, 8},
+ { -7774, 17, 12}, { -7724, 9, 11}, { -7678, 19, 12}, { -7633, 5, 10},
+ { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475, 3, 9},
+ { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341, 7, 10},
+ { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225, 1, 7},
+ { -7172, 17, 11}, { -7122, 9, 10}, { -7075, 19, 11}, { -7031, 5, 9},
+ { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873, 3, 8},
+ { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739, 7, 9},
+ { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623, 1, 6},
+ { -6570, 17, 10}, { -6520, 9, 9}, { -6473, 19, 10}, { -6429, 5, 8},
+ { -6386, 21, 10}, { -6346, 11, 9}, { -6307, 23, 10}, { -6270, 3, 7},
+ { -6235, 25, 10}, { -6201, 13, 9}, { -6168, 27, 10}, { -6137, 7, 8},
+ { -6106, 29, 10}, { -6077, 15, 9}, { -6048, 31, 10}, { -6021, 1, 5},
+ { -5968, 17, 9}, { -5918, 9, 8}, { -5871, 19, 9}, { -5827, 5, 7},
+ { -5784, 21, 9}, { -5744, 11, 8}, { -5705, 23, 9}, { -5668, 3, 6},
+ { -5633, 25, 9}, { -5599, 13, 8}, { -5566, 27, 9}, { -5535, 7, 7},
+ { -5504, 29, 9}, { -5475, 15, 8}, { -5446, 31, 9}, { -5419, 1, 4},
+ { -5366, 17, 8}, { -5316, 9, 7}, { -5269, 19, 8}, { -5225, 5, 6},
+ { -5182, 21, 8}, { -5142, 11, 7}, { -5103, 23, 8}, { -5066, 3, 5},
+ { -5031, 25, 8}, { -4997, 13, 7}, { -4964, 27, 8}, { -4932, 7, 6},
+ { -4902, 29, 8}, { -4873, 15, 7}, { -4844, 31, 8}, { -4816, 1, 3},
+ { -4764, 17, 7}, { -4714, 9, 6}, { -4667, 19, 7}, { -4623, 5, 5},
+ { -4580, 21, 7}, { -4540, 11, 6}, { -4501, 23, 7}, { -4464, 3, 4},
+ { -4429, 25, 7}, { -4395, 13, 6}, { -4362, 27, 7}, { -4330, 7, 5},
+ { -4300, 29, 7}, { -4270, 15, 6}, { -4242, 31, 7}, { -4214, 1, 2},
+ { -4162, 17, 6}, { -4112, 9, 5}, { -4065, 19, 6}, { -4021, 5, 4},
+ { -3978, 21, 6}, { -3938, 11, 5}, { -3899, 23, 6}, { -3862, 3, 3},
+ { -3827, 25, 6}, { -3793, 13, 5}, { -3760, 27, 6}, { -3728, 7, 4},
+ { -3698, 29, 6}, { -3668, 15, 5}, { -3640, 31, 6}, { -3612, 1, 1},
+ { -3560, 17, 5}, { -3510, 9, 4}, { -3463, 19, 5}, { -3419, 5, 3},
+ { -3376, 21, 5}, { -3336, 11, 4}, { -3297, 23, 5}, { -3260, 3, 2},
+ { -3225, 25, 5}, { -3191, 13, 4}, { -3158, 27, 5}, { -3126, 7, 3},
+ { -3096, 29, 5}, { -3066, 15, 4}, { -3038, 31, 5}, { -3010, 1, 0},
+ { -2958, 17, 4}, { -2908, 9, 3}, { -2861, 19, 4}, { -2816, 5, 2},
+ { -2774, 21, 4}, { -2734, 11, 3}, { -2695, 23, 4}, { -2658, 3, 1},
+ { -2623, 25, 4}, { -2589, 13, 3}, { -2556, 27, 4}, { -2524, 7, 2},
+ { -2494, 29, 4}, { -2464, 15, 3}, { -2436, 31, 4}, { -2408, 2, 0},
+ { -2356, 17, 3}, { -2306, 9, 2}, { -2259, 19, 3}, { -2214, 5, 1},
+ { -2172, 21, 3}, { -2132, 11, 2}, { -2093, 23, 3}, { -2056, 3, 0},
+ { -2021, 25, 3}, { -1987, 13, 2}, { -1954, 27, 3}, { -1922, 7, 1},
+ { -1892, 29, 3}, { -1862, 15, 2}, { -1834, 31, 3}, { -1806, 4, 0},
+ { -1754, 17, 2}, { -1704, 9, 1}, { -1657, 19, 2}, { -1612, 5, 0},
+ { -1570, 21, 2}, { -1530, 11, 1}, { -1491, 23, 2}, { -1454, 6, 0},
+ { -1419, 25, 2}, { -1384, 13, 1}, { -1352, 27, 2}, { -1320, 7, 0},
+ { -1290, 29, 2}, { -1260, 15, 1}, { -1232, 31, 2}, { -1204, 8, 0},
+ { -1151, 17, 1}, { -1102, 9, 0}, { -1055, 19, 1}, { -1010, 10, 0},
+ { -968, 21, 1}, { -928, 11, 0}, { -889, 23, 1}, { -852, 12, 0},
+ { -816, 25, 1}, { -782, 13, 0}, { -750, 27, 1}, { -718, 14, 0},
+ { -688, 29, 1}, { -658, 15, 0}, { -630, 31, 1}, { -602, 16, 0},
+ { -549, 17, 0}, { -500, 18, 0}, { -453, 19, 0}, { -408, 20, 0},
+ { -366, 21, 0}, { -325, 22, 0}, { -287, 23, 0}, { -250, 24, 0},
+ { -214, 25, 0}, { -180, 26, 0}, { -148, 27, 0}, { -116, 28, 0},
+ { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0},
+};
+
+static int pm860x_volatile(unsigned int reg)
+{
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ switch (reg) {
+ case PM860X_AUDIO_SUPPLIES_2:
+ return 1;
+ }
+
+ return 0;
+}
+
+static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned char *cache = codec->reg_cache;
+
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ if (pm860x_volatile(reg))
+ return cache[reg];
+
+ reg += REG_CACHE_BASE;
+
+ return pm860x_reg_read(codec->control_data, reg);
+}
+
+static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ unsigned char *cache = codec->reg_cache;
+
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ if (!pm860x_volatile(reg))
+ cache[reg] = (unsigned char)value;
+
+ reg += REG_CACHE_BASE;
+
+ return pm860x_reg_write(codec->control_data, reg, value);
+}
+
+static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ int val[2], val2[2], i;
+
+ val[0] = snd_soc_read(codec, reg) & 0x3f;
+ val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf;
+ val2[0] = snd_soc_read(codec, reg2) & 0x3f;
+ val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf;
+
+ for (i = 0; i < ARRAY_SIZE(st_table); i++) {
+ if ((st_table[i].m == val[0]) && (st_table[i].n == val[1]))
+ ucontrol->value.integer.value[0] = i;
+ if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1]))
+ ucontrol->value.integer.value[1] = i;
+ }
+ return 0;
+}
+
+static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ int err;
+ unsigned int val, val2;
+
+ val = ucontrol->value.integer.value[0];
+ val2 = ucontrol->value.integer.value[1];
+
+ err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
+ if (err < 0)
+ return err;
+ err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0,
+ st_table[val].n << 4);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m);
+ if (err < 0)
+ return err;
+ err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f,
+ st_table[val2].n);
+ return err;
+}
+
+static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max, val, val2;
+ unsigned int mask = (1 << fls(max)) - 1;
+
+ val = snd_soc_read(codec, reg) >> shift;
+ val2 = snd_soc_read(codec, reg2) >> shift;
+ ucontrol->value.integer.value[0] = (max - val) & mask;
+ ucontrol->value.integer.value[1] = (max - val2) & mask;
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ unsigned int mask = (1 << fls(max)) - 1;
+ int err;
+ unsigned int val, val2, val_mask;
+
+ val_mask = mask << shift;
+ val = ((max - ucontrol->value.integer.value[0]) & mask);
+ val2 = ((max - ucontrol->value.integer.value[1]) & mask);
+
+ val = val << shift;
+ val2 = val2 << shift;
+
+ err = snd_soc_update_bits(codec, reg, val_mask, val);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+ return err;
+}
+
+/* DAPM Widget Events */
+static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ /* unmute DAC */
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ return 0;
+}
+
+static int pm860x_adc_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int en1 = 0, en2 = 0;
+
+ if (!strcmp(w->name, "Left ADC")) {
+ en1 = ADC_MOD_LEFT;
+ en2 = ADC_LEFT;
+ }
+ if (!strcmp(w->name, "Right ADC")) {
+ en1 = ADC_MOD_RIGHT;
+ en2 = ADC_RIGHT;
+ }
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, PM860X_ADC_EN_1, en1, en1);
+ snd_soc_update_bits(codec, PM860X_ADC_EN_2, en2, en2);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, PM860X_ADC_EN_1, en1, 0);
+ snd_soc_update_bits(codec, PM860X_ADC_EN_2, en2, 0);
+ break;
+ }
+ return 0;
+}
+
+static int pm860x_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int dac = 0;
+ int data;
+
+ if (!strcmp(w->name, "Left DAC"))
+ dac = DAC_LEFT;
+ if (!strcmp(w->name, "Right DAC"))
+ dac = DAC_RIGHT;
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (dac) {
+ dac |= MODULATOR;
+ /* mute */
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+ DAC_MUTE, DAC_MUTE);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ /* update dac */
+ snd_soc_update_bits(codec, PM860X_DAC_EN_2,
+ dac, dac);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ if (dac) {
+ /* mute */
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+ DAC_MUTE, DAC_MUTE);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ /* update dac */
+ data = snd_soc_read(codec, PM860X_DAC_EN_2);
+ data &= ~dac;
+ if (!(data & (DAC_LEFT | DAC_RIGHT)))
+ data &= ~MODULATOR;
+ snd_soc_write(codec, PM860X_DAC_EN_2, data);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int pm860x_mic1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* Enable Mic1 Bias & MICDET, HSDET */
+ snd_soc_update_bits(codec, PM860X_ADC_ANA_1, MIC1BIAS_MASK,
+ MIC1BIAS_MASK);
+ pm860x_set_bits(codec->control_data, REG_MIC_DET,
+ MICDET_MASK, MICDET_MASK);
+ pm860x_set_bits(codec->control_data, REG_HS_DET,
+ EN_HS_DET, EN_HS_DET);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* disable Mic1 Bias & MICDET, HSDET */
+ pm860x_set_bits(codec->control_data, REG_MIC_DET,
+ MICDET_MASK, 0);
+ pm860x_set_bits(codec->control_data, REG_HS_DET,
+ EN_HS_DET, 0);
+ snd_soc_update_bits(codec, PM860X_ADC_ANA_1, MIC1BIAS_MASK, 0);
+ break;
+ }
+ return 0;
+}
+
+static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
+
+static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
+
+static const struct soc_enum pm860x_hs1_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs2_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs1_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_hs2_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo1_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo2_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo1_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo2_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_ear_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_ear_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
+
+static const struct snd_kcontrol_new pm860x_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
+ PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv),
+ SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0,
+ aux_tlv),
+ SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0,
+ mic_tlv),
+ SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0,
+ mic_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN,
+ PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1,
+ 0, snd_soc_get_volsw_2r_st,
+ snd_soc_put_volsw_2r_st, st_tlv),
+ SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1,
+ 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL,
+ PM860X_LO2_CTRL, 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL,
+ PM860X_HS2_CTRL, 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume",
+ PM860X_HIFIL_GAIN_LEFT,
+ PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume",
+ PM860X_HIFIR_GAIN_LEFT,
+ PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT,
+ PM860X_LOFI_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_ENUM("Headset1 Operational Amplifier Current",
+ pm860x_hs1_opamp_enum),
+ SOC_ENUM("Headset2 Operational Amplifier Current",
+ pm860x_hs2_opamp_enum),
+ SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum),
+ SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum),
+ SOC_ENUM("Lineout1 Operational Amplifier Current",
+ pm860x_lo1_opamp_enum),
+ SOC_ENUM("Lineout2 Operational Amplifier Current",
+ pm860x_lo2_opamp_enum),
+ SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum),
+ SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum),
+ SOC_ENUM("Speaker Operational Amplifier Current",
+ pm860x_spk_ear_opamp_enum),
+ SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum),
+ SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum),
+};
+
+/*
+ * DAPM Controls
+ */
+
+/* PCM Switch / PCM Interface */
+static const struct snd_kcontrol_new pcm_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
+
+/* AUX1 Switch */
+static const struct snd_kcontrol_new aux1_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
+
+/* AUX2 Switch */
+static const struct snd_kcontrol_new aux2_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0);
+
+/* Left Ex. PA Switch */
+static const struct snd_kcontrol_new lepa_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0);
+
+/* Right Ex. PA Switch */
+static const struct snd_kcontrol_new repa_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
+
+/* PCM Mux / Mux7 */
+static const char *aif1_text[] = {
+ "PCM L", "PCM R",
+};
+
+static const struct soc_enum aif1_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
+
+static const struct snd_kcontrol_new aif1_mux =
+ SOC_DAPM_ENUM("PCM Mux", aif1_enum);
+
+/* I2S Mux / Mux9 */
+static const char *i2s_din_text[] = {
+ "DIN", "DIN1",
+};
+
+static const struct soc_enum i2s_din_enum =
+ SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
+
+static const struct snd_kcontrol_new i2s_din_mux =
+ SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
+
+/* I2S Mic Mux / Mux8 */
+static const char *i2s_mic_text[] = {
+ "Ex PA", "ADC",
+};
+
+static const struct soc_enum i2s_mic_enum =
+ SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
+
+static const struct snd_kcontrol_new i2s_mic_mux =
+ SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
+
+/* ADCL Mux / Mux2 */
+static const char *adcl_text[] = {
+ "ADCR", "ADCL",
+};
+
+static const struct soc_enum adcl_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
+
+static const struct snd_kcontrol_new adcl_mux =
+ SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
+
+/* ADCR Mux / Mux3 */
+static const char *adcr_text[] = {
+ "ADCL", "ADCR",
+};
+
+static const struct soc_enum adcr_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
+
+static const struct snd_kcontrol_new adcr_mux =
+ SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
+
+/* ADCR EC Mux / Mux6 */
+static const char *adcr_ec_text[] = {
+ "ADCR", "EC",
+};
+
+static const struct soc_enum adcr_ec_enum =
+ SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
+
+static const struct snd_kcontrol_new adcr_ec_mux =
+ SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
+
+/* EC Mux / Mux4 */
+static const char *ec_text[] = {
+ "Left", "Right", "Left + Right",
+};
+
+static const struct soc_enum ec_enum =
+ SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
+
+static const struct snd_kcontrol_new ec_mux =
+ SOC_DAPM_ENUM("EC Mux", ec_enum);
+
+static const char *dac_text[] = {
+ "No input", "Right", "Left", "No input",
+};
+
+/* DAC Headset 1 Mux / Mux10 */
+static const struct soc_enum dac_hs1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs1_mux =
+ SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
+
+/* DAC Headset 2 Mux / Mux11 */
+static const struct soc_enum dac_hs2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs2_mux =
+ SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
+
+/* DAC Lineout 1 Mux / Mux12 */
+static const struct soc_enum dac_lo1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo1_mux =
+ SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
+
+/* DAC Lineout 2 Mux / Mux13 */
+static const struct soc_enum dac_lo2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo2_mux =
+ SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
+
+/* DAC Spearker Earphone Mux / Mux14 */
+static const struct soc_enum dac_spk_ear_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_spk_ear_mux =
+ SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
+
+/* Headset 1 Mux / Mux15 */
+static const char *in_text[] = {
+ "Digital", "Analog",
+};
+
+static const struct soc_enum hs1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
+
+static const struct snd_kcontrol_new hs1_mux =
+ SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
+
+/* Headset 2 Mux / Mux16 */
+static const struct soc_enum hs2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
+
+static const struct snd_kcontrol_new hs2_mux =
+ SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
+
+/* Lineout 1 Mux / Mux17 */
+static const struct soc_enum lo1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
+
+static const struct snd_kcontrol_new lo1_mux =
+ SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
+
+/* Lineout 2 Mux / Mux18 */
+static const struct soc_enum lo2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
+
+static const struct snd_kcontrol_new lo2_mux =
+ SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
+
+/* Speaker Earpiece Demux */
+static const char *spk_text[] = {
+ "Earpiece", "Speaker",
+};
+
+static const struct soc_enum spk_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
+
+static const struct snd_kcontrol_new spk_demux =
+ SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
+
+/* MIC Mux / Mux1 */
+static const char *mic_text[] = {
+ "Mic 1", "Mic 2",
+};
+
+static const struct soc_enum mic_enum =
+ SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
+
+static const struct snd_kcontrol_new mic_mux =
+ SOC_DAPM_ENUM("MIC Mux", mic_enum);
+
+static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0,
+ PM860X_ADC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0,
+ PM860X_PCM_IFACE_3, 1, 1),
+
+
+ SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
+ PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
+ PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
+ PM860X_I2S_IFACE_3, 5, 1),
+ SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
+ SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
+ SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
+ SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux),
+ SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux),
+ SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0,
+ &lepa_switch_controls),
+ SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0,
+ &repa_switch_controls),
+
+ SND_SOC_DAPM_ADC_E("Left ADC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_adc_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("Right ADC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_adc_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0,
+ &aux1_switch_controls),
+ SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0,
+ &aux2_switch_controls),
+
+ SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux),
+ SND_SOC_DAPM_MICBIAS_E("Mic1 Bias", SND_SOC_NOPM, 0, 0,
+ &pm860x_mic1_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0),
+ SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("AUX1"),
+ SND_SOC_DAPM_INPUT("AUX2"),
+ SND_SOC_DAPM_INPUT("MIC1P"),
+ SND_SOC_DAPM_INPUT("MIC1N"),
+ SND_SOC_DAPM_INPUT("MIC2P"),
+ SND_SOC_DAPM_INPUT("MIC2N"),
+ SND_SOC_DAPM_INPUT("MIC3P"),
+ SND_SOC_DAPM_INPUT("MIC3N"),
+
+ SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux),
+ SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux),
+ SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux),
+ SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux),
+ SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux),
+ SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux),
+ SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux),
+ SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux),
+ SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux),
+ SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux),
+ SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0,
+ &spk_demux),
+
+
+ SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("HS1"),
+ SND_SOC_DAPM_OUTPUT("HS2"),
+ SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("EARP"),
+ SND_SOC_DAPM_OUTPUT("EARN"),
+ SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LSP"),
+ SND_SOC_DAPM_OUTPUT("LSN"),
+ SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2,
+ 0, SUPPLY_MASK, SUPPLY_MASK, 0),
+
+ SND_SOC_DAPM_POST("RSYNC", pm860x_rsync_event),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* supply */
+ {"Left DAC", NULL, "VCODEC"},
+ {"Right DAC", NULL, "VCODEC"},
+ {"Left ADC", NULL, "VCODEC"},
+ {"Right ADC", NULL, "VCODEC"},
+
+ /* PCM/AIF1 Inputs */
+ {"PCM SDO", NULL, "ADC Left Mux"},
+ {"PCM SDO", NULL, "ADCR EC Mux"},
+
+ /* PCM/AFI2 Outputs */
+ {"Lofi PGA", NULL, "PCM SDI"},
+ {"Lofi PGA", NULL, "Sidetone PGA"},
+ {"Left DAC", NULL, "Lofi PGA"},
+ {"Right DAC", NULL, "Lofi PGA"},
+
+ /* I2S/AIF2 Inputs */
+ {"MIC Mux", "Mic 1", "MIC1P"},
+ {"MIC Mux", "Mic 1", "MIC1N"},
+ {"MIC Mux", "Mic 2", "MIC2P"},
+ {"MIC Mux", "Mic 2", "MIC2N"},
+ {"MIC1 Volume", NULL, "MIC Mux"},
+ {"MIC3 Volume", NULL, "MIC3P"},
+ {"MIC3 Volume", NULL, "MIC3N"},
+ {"Left ADC", NULL, "MIC1 Volume"},
+ {"Right ADC", NULL, "MIC3 Volume"},
+ {"ADC Left Mux", "ADCR", "Right ADC"},
+ {"ADC Left Mux", "ADCL", "Left ADC"},
+ {"ADC Right Mux", "ADCL", "Left ADC"},
+ {"ADC Right Mux", "ADCR", "Right ADC"},
+ {"Left EPA", "Switch", "Left DAC"},
+ {"Right EPA", "Switch", "Right DAC"},
+ {"EC Mux", "Left", "Left DAC"},
+ {"EC Mux", "Right", "Right DAC"},
+ {"EC Mux", "Left + Right", "Left DAC"},
+ {"EC Mux", "Left + Right", "Right DAC"},
+ {"ADCR EC Mux", "ADCR", "ADC Right Mux"},
+ {"ADCR EC Mux", "EC", "EC Mux"},
+ {"I2S Mic Mux", "Ex PA", "Left EPA"},
+ {"I2S Mic Mux", "Ex PA", "Right EPA"},
+ {"I2S Mic Mux", "ADC", "ADC Left Mux"},
+ {"I2S Mic Mux", "ADC", "ADCR EC Mux"},
+ {"I2S DOUT", NULL, "I2S Mic Mux"},
+
+ /* I2S/AIF2 Outputs */
+ {"I2S DIN Mux", "DIN", "I2S DIN"},
+ {"I2S DIN Mux", "DIN1", "I2S DIN1"},
+ {"Left DAC", NULL, "I2S DIN Mux"},
+ {"Right DAC", NULL, "I2S DIN Mux"},
+ {"DAC HS1 Mux", "Left", "Left DAC"},
+ {"DAC HS1 Mux", "Right", "Right DAC"},
+ {"DAC HS2 Mux", "Left", "Left DAC"},
+ {"DAC HS2 Mux", "Right", "Right DAC"},
+ {"DAC LO1 Mux", "Left", "Left DAC"},
+ {"DAC LO1 Mux", "Right", "Right DAC"},
+ {"DAC LO2 Mux", "Left", "Left DAC"},
+ {"DAC LO2 Mux", "Right", "Right DAC"},
+ {"Headset1 Mux", "Digital", "DAC HS1 Mux"},
+ {"Headset2 Mux", "Digital", "DAC HS2 Mux"},
+ {"Lineout1 Mux", "Digital", "DAC LO1 Mux"},
+ {"Lineout2 Mux", "Digital", "DAC LO2 Mux"},
+ {"Headset1 PGA", NULL, "Headset1 Mux"},
+ {"Headset2 PGA", NULL, "Headset2 Mux"},
+ {"Lineout1 PGA", NULL, "Lineout1 Mux"},
+ {"Lineout2 PGA", NULL, "Lineout2 Mux"},
+ {"DAC SP Mux", "Left", "Left DAC"},
+ {"DAC SP Mux", "Right", "Right DAC"},
+ {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"},
+ {"Speaker PGA", NULL, "Speaker Earpiece Demux"},
+ {"Earpiece PGA", NULL, "Speaker Earpiece Demux"},
+
+ {"HS1", NULL, "Headset1 PGA"},
+ {"HS2", NULL, "Headset2 PGA"},
+ {"LINEOUT1", NULL, "Lineout1 PGA"},
+ {"LINEOUT2", NULL, "Lineout2 PGA"},
+ {"LSP", NULL, "Speaker PGA"},
+ {"LSN", NULL, "Speaker PGA"},
+ {"EARP", NULL, "Earpiece PGA"},
+ {"EARN", NULL, "Earpiece PGA"},
+};
+
+static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int data = 0;
+
+ if (mute)
+ data = DAC_MUTE;
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, data);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ return 0;
+}
+
+static int set_dai_fmt(struct pm860x_priv *pm860x, unsigned int fmt,
+ unsigned char *inf, unsigned char *mask)
+{
+ *mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ if (pm860x->dir == PM860X_CLK_DIR_OUT)
+ *inf |= PCM_INF2_MASTER;
+ else
+ return -EINVAL;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ if (pm860x->dir == PM860X_CLK_DIR_IN)
+ *inf &= ~PCM_INF2_MASTER;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ *inf |= PCM_EXACT_I2S;
+ break;
+ default:
+ return -EINVAL;
+ }
+ *mask |= PCM_MODE_MASK;
+ return 0;
+}
+
+static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned char inf = 0, mask = 0;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ inf &= ~PCM_INF2_18WL;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ inf |= PCM_INF2_18WL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mask |= PCM_INF2_18WL;
+ snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+
+ /* sample rate */
+ switch (params_rate(params)) {
+ case 8000:
+ inf = 0;
+ break;
+ case 16000:
+ inf = 3;
+ break;
+ case 32000:
+ inf = 6;
+ break;
+ case 48000:
+ inf = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf);
+
+ return 0;
+}
+
+static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ unsigned char inf = 0, mask = 0;
+ int ret;
+
+ ret = set_dai_fmt(pm860x, fmt, &inf, &mask);
+ if (!ret)
+ snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+ return ret;
+}
+
+static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+
+ if (dir == PM860X_CLK_DIR_OUT)
+ pm860x->dir = PM860X_CLK_DIR_OUT;
+ else
+ pm860x->dir = PM860X_CLK_DIR_IN;
+
+ return 0;
+}
+
+static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned char inf;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ inf = 0;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ inf = PCM_INF2_18WL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf);
+
+ /* sample rate */
+ switch (params_rate(params)) {
+ case 8000:
+ inf = 0;
+ break;
+ case 11025:
+ inf = 1;
+ break;
+ case 16000:
+ inf = 3;
+ break;
+ case 22050:
+ inf = 4;
+ break;
+ case 32000:
+ inf = 6;
+ break;
+ case 44100:
+ inf = 7;
+ break;
+ case 48000:
+ inf = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf);
+
+ return 0;
+}
+
+static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ unsigned char inf = 0, mask = 0;
+ int ret;
+
+ ret = set_dai_fmt(pm860x, fmt, &inf, &mask);
+ if (!ret)
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf);
+ return ret;
+}
+
+static int pm860x_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ int data;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Enable Audio PLL & Audio section */
+ data = AUDIO_PLL | AUDIO_SECTION_RESET
+ | AUDIO_SECTION_ON;
+ pm860x_reg_write(codec->control_data, REG_MISC2, data);
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
+ pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+ .digital_mute = pm860x_digital_mute,
+ .hw_params = pm860x_pcm_hw_params,
+ .set_fmt = pm860x_pcm_set_dai_fmt,
+ .set_sysclk = pm860x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+ .digital_mute = pm860x_digital_mute,
+ .hw_params = pm860x_i2s_hw_params,
+ .set_fmt = pm860x_i2s_set_dai_fmt,
+ .set_sysclk = pm860x_set_dai_sysclk,
+};
+
+#define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+
+static struct snd_soc_dai_driver pm860x_dai[] = {
+ {
+ /* DAI PCM */
+ .name = "88pm860x-pcm",
+ .id = 1,
+ .playback = {
+ .stream_name = "PCM Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = PM860X_RATES,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .capture = {
+ .stream_name = "PCM Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = PM860X_RATES,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .ops = &pm860x_pcm_dai_ops,
+ }, {
+ /* DAI I2S */
+ .name = "88pm860x-i2s",
+ .id = 2,
+ .playback = {
+ .stream_name = "I2S Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .capture = {
+ .stream_name = "I2S Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .ops = &pm860x_i2s_dai_ops,
+ },
+};
+
+static irqreturn_t pm860x_codec_handler(int irq, void *data)
+{
+ struct pm860x_priv *pm860x = data;
+ int status, shrt, report = 0;
+
+ status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1);
+ shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS);
+
+ if (status & HEADSET_STATUS)
+ report |= PM860X_DET_HEADSET;
+ if (status & MIC_STATUS)
+ report |= PM860X_DET_MIC;
+ if (status & HOOK_STATUS)
+ report |= PM860X_DET_HOOK;
+ if (shrt & (SHORT_LO1 | SHORT_LO2))
+ report |= PM860X_SHORT_LINEOUT;
+ if (shrt & (SHORT_HS1 | SHORT_HS2))
+ report |= PM860X_SHORT_HEADSET;
+ dev_dbg(pm860x->codec->dev, "report:0x%x\n", report);
+ return IRQ_HANDLED;
+}
+
+static int pm860x_probe(struct snd_soc_codec *codec)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ int i, ret;
+
+ pm860x->codec = codec;
+
+ codec->control_data = pm860x->i2c;
+
+ for (i = 0; i < 4; i++) {
+ ret = request_threaded_irq(pm860x->irq[i], NULL,
+ pm860x_codec_handler, IRQF_ONESHOT,
+ pm860x->name[i], pm860x);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to request IRQ!\n");
+ goto out_irq;
+ }
+ }
+
+ pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
+ REG_CACHE_SIZE, codec->reg_cache);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to fill register cache: %d\n",
+ ret);
+ goto out_codec;
+ }
+
+ snd_soc_add_controls(codec, pm860x_snd_controls,
+ ARRAY_SIZE(pm860x_snd_controls));
+ snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets,
+ ARRAY_SIZE(pm860x_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ return 0;
+
+out_codec:
+ i = 3;
+out_irq:
+ for (; i >= 0; i--)
+ free_irq(pm860x->irq[i], pm860x);
+ return -EINVAL;
+}
+
+static int pm860x_remove(struct snd_soc_codec *codec)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ for (i = 3; i >= 0; i--)
+ free_irq(pm860x->irq[i], pm860x);
+ pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
+ .probe = pm860x_probe,
+ .remove = pm860x_remove,
+ .read = pm860x_read_reg_cache,
+ .write = pm860x_write_reg_cache,
+ .reg_cache_size = REG_CACHE_SIZE,
+ .reg_word_size = sizeof(u8),
+ .set_bias_level = pm860x_set_bias_level,
+};
+
+static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_priv *pm860x;
+ struct resource *res;
+ int i, ret;
+
+ pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL);
+ if (pm860x == NULL)
+ return -ENOMEM;
+
+ pm860x->chip = chip;
+ pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
+ : chip->companion;
+ platform_set_drvdata(pdev, pm860x);
+
+ for (i = 0; i < 4; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get IRQ resources\n");
+ goto out;
+ }
+ pm860x->irq[i] = res->start + chip->irq_base;
+ strncpy(pm860x->name[i], res->name, MAX_NAME_LEN);
+ }
+
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x,
+ pm860x_dai, ARRAY_SIZE(pm860x_dai));
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register codec\n");
+ goto out;
+ }
+ return ret;
+
+out:
+ platform_set_drvdata(pdev, NULL);
+ kfree(pm860x);
+ return -EINVAL;
+}
+
+static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+{
+ struct pm860x_priv *pm860x = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_codec(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(pm860x);
+ return 0;
+}
+
+static struct platform_driver pm860x_codec_driver = {
+ .driver = {
+ .name = "88pm860x-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_codec_probe,
+ .remove = __devexit_p(pm860x_codec_remove),
+};
+
+static __init int pm860x_init(void)
+{
+ return platform_driver_register(&pm860x_codec_driver);
+}
+module_init(pm860x_init);
+
+static __exit void pm860x_exit(void)
+{
+ platform_driver_unregister(&pm860x_codec_driver);
+}
+module_exit(pm860x_exit);
+
+MODULE_DESCRIPTION("ASoC 88PM860x driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang(a)marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-codec");
+
diff --git a/sound/soc/codecs/88pm860x-codec.h
b/sound/soc/codecs/88pm860x-codec.h
new file mode 100644
index 0000000..b034de2
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.h
@@ -0,0 +1,92 @@
+/*
+ * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang(a)marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __88PM860X_H
+#define __88PM860X_H
+
+/* The offset of these registers are 0xb0 */
+#define PM860X_PCM_IFACE_1 0x00
+#define PM860X_PCM_IFACE_2 0x01
+#define PM860X_PCM_IFACE_3 0x02
+#define PM860X_PCM_RATE 0x03
+#define PM860X_EC_PATH 0x04
+#define PM860X_SIDETONE_L_GAIN 0x05
+#define PM860X_SIDETONE_R_GAIN 0x06
+#define PM860X_SIDETONE_SHIFT 0x07
+#define PM860X_ADC_OFFSET_1 0x08
+#define PM860X_ADC_OFFSET_2 0x09
+#define PM860X_DMIC_DELAY 0x0a
+
+#define PM860X_I2S_IFACE_1 0x0b
+#define PM860X_I2S_IFACE_2 0x0c
+#define PM860X_I2S_IFACE_3 0x0d
+#define PM860X_I2S_IFACE_4 0x0e
+#define PM860X_EQUALIZER_N0_1 0x0f
+#define PM860X_EQUALIZER_N0_2 0x10
+#define PM860X_EQUALIZER_N1_1 0x11
+#define PM860X_EQUALIZER_N1_2 0x12
+#define PM860X_EQUALIZER_D1_1 0x13
+#define PM860X_EQUALIZER_D1_2 0x14
+#define PM860X_LOFI_GAIN_LEFT 0x15
+#define PM860X_LOFI_GAIN_RIGHT 0x16
+#define PM860X_HIFIL_GAIN_LEFT 0x17
+#define PM860X_HIFIL_GAIN_RIGHT 0x18
+#define PM860X_HIFIR_GAIN_LEFT 0x19
+#define PM860X_HIFIR_GAIN_RIGHT 0x1a
+#define PM860X_DAC_OFFSET 0x1b
+#define PM860X_OFFSET_LEFT_1 0x1c
+#define PM860X_OFFSET_LEFT_2 0x1d
+#define PM860X_OFFSET_RIGHT_1 0x1e
+#define PM860X_OFFSET_RIGHT_2 0x1f
+#define PM860X_ADC_ANA_1 0x20
+#define PM860X_ADC_ANA_2 0x21
+#define PM860X_ADC_ANA_3 0x22
+#define PM860X_ADC_ANA_4 0x23
+#define PM860X_ANA_TO_ANA 0x24
+#define PM860X_HS1_CTRL 0x25
+#define PM860X_HS2_CTRL 0x26
+#define PM860X_LO1_CTRL 0x27
+#define PM860X_LO2_CTRL 0x28
+#define PM860X_EAR_CTRL_1 0x29
+#define PM860X_EAR_CTRL_2 0x2a
+#define PM860X_AUDIO_SUPPLIES_1 0x2b
+#define PM860X_AUDIO_SUPPLIES_2 0x2c
+#define PM860X_ADC_EN_1 0x2d
+#define PM860X_ADC_EN_2 0x2e
+#define PM860X_DAC_EN_1 0x2f
+#define PM860X_DAC_EN_2 0x31
+#define PM860X_AUDIO_CAL_1 0x32
+#define PM860X_AUDIO_CAL_2 0x33
+#define PM860X_AUDIO_CAL_3 0x34
+#define PM860X_AUDIO_CAL_4 0x35
+#define PM860X_AUDIO_CAL_5 0x36
+#define PM860X_ANA_INPUT_SEL_1 0x37
+#define PM860X_ANA_INPUT_SEL_2 0x38
+
+#define PM860X_PCM_IFACE_4 0x39
+#define PM860X_I2S_IFACE_5 0x3a
+
+#define PM860X_SHORTS 0x3b
+#define PM860X_PLL_ADJ_1 0x3c
+#define PM860X_PLL_ADJ_2 0x3d
+
+/* bits definition */
+#define PM860X_CLK_DIR_IN 0
+#define PM860X_CLK_DIR_OUT 1
+
+#define PM860X_DET_HEADSET (1 << 0)
+#define PM860X_DET_MIC (1 << 1)
+#define PM860X_DET_HOOK (1 << 2)
+#define PM860X_SHORT_HEADSET (1 << 3)
+#define PM860X_SHORT_LINEOUT (1 << 4)
+#define PM860X_DET_MASK 0x1F
+
+#endif /* __88PM860X_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bfdd92b..a3cfc18 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
+ select SND_SOC_88PM860X if MFD_88PM860X
select SND_SOC_L3
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
select SND_SOC_AD1836 if SPI_MASTER
@@ -85,6 +86,9 @@ config SND_SOC_ALL_CODECS
If unsure select "N".
+config SND_SOC_88PM860X
+ tristate
+
config SND_SOC_WM_HUBS
tristate
default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 9c3c39f..b9c4358 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,3 +1,4 @@
+snd-soc-88pm860x-objs := 88pm860x-codec.o
snd-soc-ac97-objs := ac97.o
snd-soc-ad1836-objs := ad1836.o
snd-soc-ad193x-objs := ad193x.o
@@ -67,6 +68,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-wm2000-objs := wm2000.o
snd-soc-wm9090-objs := wm9090.o
+obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
--
1.5.6.5
--0016e6d63f44021a1f048e002b69
Content-Type: text/x-patch; charset=US-ASCII;
name="0001-ASoC-add-88pm860x-codec-driver.patch"
Content-Disposition: attachment;
filename="0001-ASoC-add-88pm860x-codec-driver.patch"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_gcyfxo2w0
RnJvbSBjMDBjZmU3NDU2MjQyYWNjY2I1NjFiYzVhMTY4MzAwMTU4ZWNkNGE0IE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBIYW9qaWFuIFpodWFuZyA8aGFvamlhbi56aHVhbmdAbWFydmVs
bC5jb20+CkRhdGU6IFRodSwgMTIgQXVnIDIwMTAgMTI6MDE6NDcgKzA4MDAKU3ViamVjdDogW1BB
VENIIDEvM10gQVNvQzogYWRkIDg4cG04NjB4IGNvZGVjIGRyaXZlcgoKQWRkIDg4UE04NjB4IGNv
ZGVjIGRyaXZlci4gODhQTTg2MHggY29kZWMgc3VwcG9ydHMgdHdvIGludGVyZmFjZXMuIEFuZCBp
dAphbHNvIHN1cHBvcnRzIGhlYWRzZXQvbWljL2hvb2svc2hvcnQgZGV0ZWN0aW9uLgoKU2lnbmVk
LW9mZi1ieTogSGFvamlhbiBaaHVhbmcgPGhhb2ppYW4uemh1YW5nQG1hcnZlbGwuY29tPgotLS0K
IHNvdW5kL3NvYy9jb2RlY3MvODhwbTg2MHgtY29kZWMuYyB8IDE0MTAgKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKwogc291bmQvc29jL2NvZGVjcy84OHBtODYweC1jb2RlYy5o
IHwgICA5MiArKysKIHNvdW5kL3NvYy9jb2RlY3MvS2NvbmZpZyAgICAgICAgICB8ICAgIDQgKwog
c291bmQvc29jL2NvZGVjcy9NYWtlZmlsZSAgICAgICAgIHwgICAgMiArCiA0IGZpbGVzIGNoYW5n
ZWQsIDE1MDggaW5zZXJ0aW9ucygrKSwgMCBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0
NCBzb3VuZC9zb2MvY29kZWNzLzg4cG04NjB4LWNvZGVjLmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBz
b3VuZC9zb2MvY29kZWNzLzg4cG04NjB4LWNvZGVjLmgKCmRpZmYgLS1naXQgYS9zb3VuZC9zb2Mv
Y29kZWNzLzg4cG04NjB4LWNvZGVjLmMgYi9zb3VuZC9zb2MvY29kZWNzLzg4cG04NjB4LWNvZGVj
LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uMWFjYjFmMQotLS0gL2Rldi9u
dWxsCisrKyBiL3NvdW5kL3NvYy9jb2RlY3MvODhwbTg2MHgtY29kZWMuYwpAQCAtMCwwICsxLDE0
MTAgQEAKKy8qCisgKiA4OHBtODYweC1jb2RlYy5jIC0tIDg4UE04NjB4IEFMU0EgU29DIEF1ZGlv
IERyaXZlcgorICoKKyAqIENvcHlyaWdodCAyMDEwIE1hcnZlbGwgSW50ZXJuYXRpb25hbCBMdGQu
CisgKiBBdXRob3I6IEhhb2ppYW4gWmh1YW5nIDxoYW9qaWFuLnpodWFuZ0BtYXJ2ZWxsLmNvbT4K
KyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1
dGUgaXQgYW5kL29yIG1vZGlmeQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2Vu
ZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgYXMKKyAqIHB1Ymxpc2hlZCBieSB0aGUgRnJl
ZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICovCisKKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4K
KyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9pMmMuaD4KKyNpbmNs
dWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9tZmQvODhwbTg2
MHguaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSA8c291bmQvY29yZS5oPgor
I2luY2x1ZGUgPHNvdW5kL3BjbS5oPgorI2luY2x1ZGUgPHNvdW5kL3BjbV9wYXJhbXMuaD4KKyNp
bmNsdWRlIDxzb3VuZC9zb2MuaD4KKyNpbmNsdWRlIDxzb3VuZC9zb2MtZGFwbS5oPgorI2luY2x1
ZGUgPHNvdW5kL3Rsdi5oPgorI2luY2x1ZGUgPHNvdW5kL2luaXR2YWwuaD4KKworI2luY2x1ZGUg
Ijg4cG04NjB4LWNvZGVjLmgiCisKKyNkZWZpbmUgTUFYX05BTUVfTEVOCQkyMAorI2RlZmluZSBS
RUdfQ0FDSEVfU0laRQkJMHg0MAorI2RlZmluZSBSRUdfQ0FDSEVfQkFTRQkJMHhiMAorCisvKiBT
dGF0dXMgUmVnaXN0ZXIgMSAoMHgwMSkgKi8KKyNkZWZpbmUgUkVHX1NUQVRVU18xCQkweDAxCisj
ZGVmaW5lIE1JQ19TVEFUVVMJCSgxIDw8IDcpCisjZGVmaW5lIEhPT0tfU1RBVFVTCQkoMSA8PCA2
KQorI2RlZmluZSBIRUFEU0VUX1NUQVRVUwkJKDEgPDwgNSkKKworLyogTWljIERldGVjdGlvbiBS
ZWdpc3RlciAoMHgzNykgKi8KKyNkZWZpbmUgUkVHX01JQ19ERVQJCTB4MzcKKyNkZWZpbmUgQ09O
VElOVU9VU19QT0xMSU5HCSgzIDw8IDEpCisjZGVmaW5lIEVOX01JQ19ERVQJCSgxIDw8IDApCisj
ZGVmaW5lIE1JQ0RFVF9NQVNLCQkweDA3CisKKy8qIEhlYWRzZXQgRGV0ZWN0aW9uIFJlZ2lzdGVy
ICgweDM4KSAqLworI2RlZmluZSBSRUdfSFNfREVUCQkweDM4CisjZGVmaW5lIEVOX0hTX0RFVAkJ
KDEgPDwgMCkKKworLyogTWlzYzIgUmVnaXN0ZXIgKDB4NDIpICovCisjZGVmaW5lIFJFR19NSVND
MgkJMHg0MgorI2RlZmluZSBBVURJT19QTEwJCSgxIDw8IDUpCisjZGVmaW5lIEFVRElPX1NFQ1RJ
T05fUkVTRVQJKDEgPDwgNCkKKyNkZWZpbmUgQVVESU9fU0VDVElPTl9PTgkoMSA8PCAzKQorCisv
KiBQQ00gSW50ZXJmYWNlIFJlZ2lzdGVyIDIgKDB4YjEpICovCisjZGVmaW5lIFBDTV9JTkYyX0JD
TEsJCSgxIDw8IDYpCS8qIEJpdCBjbG9jayBwb2xhcml0eSAqLworI2RlZmluZSBQQ01fSU5GMl9G
UwkJKDEgPDwgNSkJLyogRnJhbWUgU3luYyBwb2xhcml0eSAqLworI2RlZmluZSBQQ01fSU5GMl9N
QVNURVIJCSgxIDw8IDQpCS8qIE1hc3RlciAvIFNsYXZlICovCisjZGVmaW5lIFBDTV9JTkYyXzE4
V0wJCSgxIDw8IDMpCS8qIDE4IC8gMTYgYml0cyAqLworI2RlZmluZSBQQ01fR0VORVJBTF9JMlMJ
CTAKKyNkZWZpbmUgUENNX0VYQUNUX0kyUwkJMQorI2RlZmluZSBQQ01fTEVGVF9JMlMJCTIKKyNk
ZWZpbmUgUENNX1JJR0hUX0kyUwkJMworI2RlZmluZSBQQ01fU0hPUlRfRlMJCTQKKyNkZWZpbmUg
UENNX0xPTkdfRlMJCTUKKyNkZWZpbmUgUENNX01PREVfTUFTSwkJNworCisvKiBJMlMgSW50ZXJm
YWNlIFJlZ2lzdGVyIDQgKDB4YmUpICovCisjZGVmaW5lIEkyU19FUVVfQllQCQkoMSA8PCA2KQor
CisvKiBEQUMgT2Zmc2V0IFJlZ2lzdGVyICgweGNiKSAqLworI2RlZmluZSBEQUNfTVVURQkJKDEg
PDwgNykKKworLyogQURDIEFuYWxvZyBSZWdpc3RlciAxICgweGQwKSAqLworI2RlZmluZSBSRUdf
QURDX0FOQV8xCQkweGQwCisjZGVmaW5lIE1JQzFCSUFTX01BU0sJCTB4NjAKKworLyogRWFycGll
Y2UvU3BlYWtlciBDb250cm9sIFJlZ2lzdGVyIDIgKDB4ZGEpICovCisjZGVmaW5lIFJFR19FQVIy
CQkweGRhCisjZGVmaW5lIFJTWU5DX0NIQU5HRQkJKDEgPDwgMikKKworLyogQXVkaW8gU3VwcGxp
ZXMgUmVnaXN0ZXIgMiAoMHhkYykgKi8KKyNkZWZpbmUgUkVHX1NVUFBMSUVTMgkJMHhkYworI2Rl
ZmluZSBMRE8xNV9SRUFEWQkJKDEgPDwgNCkKKyNkZWZpbmUgTERPMTVfRU4JCSgxIDw8IDMpCisj
ZGVmaW5lIENQVU1QX1JFQURZCQkoMSA8PCAyKQorI2RlZmluZSBDUFVNUF9FTgkJKDEgPDwgMSkK
KyNkZWZpbmUgQVVESU9fRU4JCSgxIDw8IDApCisjZGVmaW5lIFNVUFBMWV9NQVNLCQkoTERPMTVf
RU4gfCBDUFVNUF9FTiB8IEFVRElPX0VOKQorCisvKiBBdWRpbyBFbmFibGUgUmVnaXN0ZXIgMSAo
MHhkZCkgKi8KKyNkZWZpbmUgQURDX01PRF9SSUdIVAkJKDEgPDwgMSkKKyNkZWZpbmUgQURDX01P
RF9MRUZUCQkoMSA8PCAwKQorCisvKiBBdWRpbyBFbmFibGUgUmVnaXN0ZXIgMiAoMHhkZSkgKi8K
KyNkZWZpbmUgQURDX0xFRlQJCSgxIDw8IDUpCisjZGVmaW5lIEFEQ19SSUdIVAkJKDEgPDwgNCkK
KworLyogREFDIEVuYWJsZSBSZWdpc3RlciAyICgweGUxKSAqLworI2RlZmluZSBEQUNfTEVGVAkJ
KDEgPDwgNSkKKyNkZWZpbmUgREFDX1JJR0hUCQkoMSA8PCA0KQorI2RlZmluZSBNT0RVTEFUT1IJ
CSgxIDw8IDMpCisKKy8qIFNob3J0cyBSZWdpc3RlciAoMHhlYikgKi8KKyNkZWZpbmUgUkVHX1NI
T1JUUwkJMHhlYgorI2RlZmluZSBTSE9SVF9MTzIJCSgxIDw8IDYpCisjZGVmaW5lIFNIT1JUX0xP
MQkJKDEgPDwgNCkKKyNkZWZpbmUgU0hPUlRfSFMyCQkoMSA8PCAyKQorI2RlZmluZSBTSE9SVF9I
UzEJCSgxIDw8IDApCisKK2VudW0geworCUZJTFRFUl9CWVBBU1MgPSAwLAorCUZJTFRFUl9MT1df
UEFTU18xLAorCUZJTFRFUl9MT1dfUEFTU18yLAorCUZJTFRFUl9ISUdIX1BBU1NfMywKKwlGSUxU
RVJfTUFYLAorfTsKKworc3RydWN0IHBtODYweF9wcml2IHsKKwl1bnNpZ25lZCBpbnQJCXN5c2Ns
azsKKwl1bnNpZ25lZCBpbnQJCXBjbWNsazsKKwl1bnNpZ25lZCBpbnQJCWRpcjsKKwl1bnNpZ25l
ZCBpbnQJCWZpbHRlcjsKKwlzdHJ1Y3Qgc25kX3NvY19jb2RlYwkqY29kZWM7CisJc3RydWN0IGky
Y19jbGllbnQJKmkyYzsKKwlzdHJ1Y3QgcG04NjB4X2NoaXAJKmNoaXA7CisKKwlpbnQJCQlpcnFb
NF07CisJdW5zaWduZWQgY2hhcgkJbmFtZVs0XVtNQVhfTkFNRV9MRU5dOworCXVuc2lnbmVkIGNo
YXIJCXJlZ19jYWNoZVtSRUdfQ0FDSEVfU0laRV07Cit9OworCisvKiAtOTQ1MGRCIHRvIDBkQiBp
biAxNTBkQiBzdGVwcyAoIG11dGUgaW5zdGVhZCBvZiAtOTQ1MGRCKSAqLworc3RhdGljIGNvbnN0
IERFQ0xBUkVfVExWX0RCX1NDQUxFKGRwZ2FfdGx2LCAtOTQ1MCwgMTUwLCAxKTsKKworLyogLTlk
QiB0byAwZGIgaW4gM2RCIHN0ZXBzICovCitzdGF0aWMgY29uc3QgREVDTEFSRV9UTFZfREJfU0NB
TEUoYWRjX3RsdiwgLTkwMCwgMzAwLCAwKTsKKworLyogey0yMywgLTE3LCAtMTMuNSwgLTExLCAt
OSwgLTYsIC0zLCAwfWRCICovCitzdGF0aWMgY29uc3QgdW5zaWduZWQgaW50IG1pY190bHZbXSA9
IHsKKwlUTFZfREJfUkFOR0VfSEVBRCg1KSwKKwkwLCAwLCBUTFZfREJfU0NBTEVfSVRFTSgtMjMw
MCwgMCwgMCksCisJMSwgMSwgVExWX0RCX1NDQUxFX0lURU0oLTE3MDAsIDAsIDApLAorCTIsIDIs
IFRMVl9EQl9TQ0FMRV9JVEVNKC0xMzUwLCAwLCAwKSwKKwkzLCAzLCBUTFZfREJfU0NBTEVfSVRF
TSgtMTEwMCwgMCwgMCksCisJNCwgNywgVExWX0RCX1NDQUxFX0lURU0oLTkwMCwgMzAwLCAwKSwK
K307CisKKy8qIHswLCAwLCAwLCAtNiwgMCwgNiwgMTIsIDE4fWRCICovCitzdGF0aWMgY29uc3Qg
dW5zaWduZWQgaW50IGF1eF90bHZbXSA9IHsKKwlUTFZfREJfUkFOR0VfSEVBRCgyKSwKKwkwLCAy
LCBUTFZfREJfU0NBTEVfSVRFTSgwLCAwLCAwKSwKKwkzLCA3LCBUTFZfREJfU0NBTEVfSVRFTSgt
NjAwLCA2MDAsIDApLAorfTsKKworLyogey0xNiwgLTEzLCAtMTAsIC03LCAtNS4yLCAtMywzLCAt
Mi4yLCAwfWRCLCBtdXRlIGluc3RlYWQgb2YgLTE2ZEIgKi8KK3N0YXRpYyBjb25zdCB1bnNpZ25l
ZCBpbnQgb3V0X3RsdltdID0geworCVRMVl9EQl9SQU5HRV9IRUFEKDQpLAorCTAsIDMsIFRMVl9E
Ql9TQ0FMRV9JVEVNKC0xNjAwLCAzMDAsIDEpLAorCTQsIDQsIFRMVl9EQl9TQ0FMRV9JVEVNKC01
MjAsIDAsIDApLAorCTUsIDUsIFRMVl9EQl9TQ0FMRV9JVEVNKC0zMzAsIDAsIDApLAorCTYsIDcs
IFRMVl9EQl9TQ0FMRV9JVEVNKC0yMjAsIDIyMCwgMCksCit9OworCitzdGF0aWMgY29uc3QgdW5z
aWduZWQgaW50IHN0X3RsdltdID0geworCVRMVl9EQl9SQU5HRV9IRUFEKDgpLAorCTAsIDEsIFRM
Vl9EQl9TQ0FMRV9JVEVNKC0xMjA0MSwgNjAyLCAwKSwKKwkyLCAzLCBUTFZfREJfU0NBTEVfSVRF
TSgtMTEwODcsIDI1MCwgMCksCisJNCwgNSwgVExWX0RCX1NDQUxFX0lURU0oLTEwNjQzLCAxNTgs
IDApLAorCTYsIDcsIFRMVl9EQl9TQ0FMRV9JVEVNKC0xMDM1MSwgMTE2LCAwKSwKKwk4LCA5LCBU
TFZfREJfU0NBTEVfSVRFTSgtMTAxMzMsIDkyLCAwKSwKKwkxMCwgMTMsIFRMVl9EQl9TQ0FMRV9J
VEVNKC05OTU4LCA3MCwgMCksCisJMTQsIDE3LCBUTFZfREJfU0NBTEVfSVRFTSgtOTY4OSwgNTMs
IDApLAorCTE4LCAyNzEsIFRMVl9EQl9TQ0FMRV9JVEVNKC05NDg0LCAzNywgMCksCit9OworCisv
KiBTaWRldG9uZSBHYWluID0gTSAqIDJeKC01LU4pICovCitzdHJ1Y3Qgc3RfZ2FpbiB7CisJdW5z
aWduZWQgaW50CWRiOworCXVuc2lnbmVkIGludAltOworCXVuc2lnbmVkIGludAluOworfTsKKwor
c3RhdGljIHN0cnVjdCBzdF9nYWluIHN0X3RhYmxlW10gPSB7CisJey0xMjA0MSwgIDEsIDE1fSwg
ey0xMTQzOSwgIDEsIDE0fSwgey0xMTA4NywgIDMsIDE1fSwgey0xMDgzNywgIDEsIDEzfSwKKwl7
LTEwNjQzLCAgNSwgMTV9LCB7LTEwNDg1LCAgMywgMTR9LCB7LTEwMzUxLCAgNywgMTV9LCB7LTEw
MjM1LCAgMSwgMTJ9LAorCXstMTAxMzMsICA5LCAxNX0sIHstMTAwNDEsICA1LCAxNH0sIHsgLTk5
NTgsIDExLCAxNX0sIHsgLTk4ODMsICAzLCAxM30sCisJeyAtOTgxMywgMTMsIDE1fSwgeyAtOTc0
OSwgIDcsIDE0fSwgeyAtOTY4OSwgMTUsIDE1fSwgeyAtOTYzMywgIDEsIDExfSwKKwl7IC05NTgw
LCAxNywgMTV9LCB7IC05NTMxLCAgOSwgMTR9LCB7IC05NDg0LCAxOSwgMTV9LCB7IC05NDM5LCAg
NSwgMTN9LAorCXsgLTkzOTcsIDIxLCAxNX0sIHsgLTkzNTYsIDExLCAxNH0sIHsgLTkzMTgsIDIz
LCAxNX0sIHsgLTkyODEsICAzLCAxMn0sCisJeyAtOTI0NSwgMjUsIDE1fSwgeyAtOTIxMSwgMTMs
IDE0fSwgeyAtOTE3OCwgMjcsIDE1fSwgeyAtOTE0NywgIDcsIDEzfSwKKwl7IC05MTE2LCAyOSwg
MTV9LCB7IC05MDg3LCAxNSwgMTR9LCB7IC05MDU4LCAzMSwgMTV9LCB7IC05MDMxLCAgMSwgMTB9
LAorCXsgLTg5NzgsIDE3LCAxNH0sIHsgLTg5MjksICA5LCAxM30sIHsgLTg4ODIsIDE5LCAxNH0s
IHsgLTg4MzcsICA1LCAxMn0sCisJeyAtODc5NSwgMjEsIDE0fSwgeyAtODc1NCwgMTEsIDEzfSwg
eyAtODcxNiwgMjMsIDE0fSwgeyAtODY3OSwgIDMsIDExfSwKKwl7IC04NjQzLCAyNSwgMTR9LCB7
IC04NjA5LCAxMywgMTN9LCB7IC04NTc2LCAyNywgMTR9LCB7IC04NTQ1LCAgNywgMTJ9LAorCXsg
LTg1MTQsIDI5LCAxNH0sIHsgLTg0ODUsIDE1LCAxM30sIHsgLTg0NTYsIDMxLCAxNH0sIHsgLTg0
MjksICAxLCAgOX0sCisJeyAtODM3NiwgMTcsIDEzfSwgeyAtODMyNywgIDksIDEyfSwgeyAtODI4
MCwgMTksIDEzfSwgeyAtODIzNSwgIDUsIDExfSwKKwl7IC04MTkzLCAyMSwgMTN9LCB7IC04MTUy
LCAxMSwgMTJ9LCB7IC04MTE0LCAyMywgMTN9LCB7IC04MDc3LCAgMywgMTB9LAorCXsgLTgwNDEs
IDI1LCAxM30sIHsgLTgwMDcsIDEzLCAxMn0sIHsgLTc5NzQsIDI3LCAxM30sIHsgLTc5NDMsICA3
LCAxMX0sCisJeyAtNzkxMiwgMjksIDEzfSwgeyAtNzg4MywgMTUsIDEyfSwgeyAtNzg1NCwgMzEs
IDEzfSwgeyAtNzgyNywgIDEsICA4fSwKKwl7IC03Nzc0LCAxNywgMTJ9LCB7IC03NzI0LCAgOSwg
MTF9LCB7IC03Njc4LCAxOSwgMTJ9LCB7IC03NjMzLCAgNSwgMTB9LAorCXsgLTc1OTEsIDIxLCAx
Mn0sIHsgLTc1NTAsIDExLCAxMX0sIHsgLTc1MTIsIDIzLCAxMn0sIHsgLTc0NzUsICAzLCAgOX0s
CisJeyAtNzQzOSwgMjUsIDEyfSwgeyAtNzQwNSwgMTMsIDExfSwgeyAtNzM3MiwgMjcsIDEyfSwg
eyAtNzM0MSwgIDcsIDEwfSwKKwl7IC03MzEwLCAyOSwgMTJ9LCB7IC03MjgxLCAxNSwgMTF9LCB7
IC03MjUyLCAzMSwgMTJ9LCB7IC03MjI1LCAgMSwgIDd9LAorCXsgLTcxNzIsIDE3LCAxMX0sIHsg
LTcxMjIsICA5LCAxMH0sIHsgLTcwNzUsIDE5LCAxMX0sIHsgLTcwMzEsICA1LCAgOX0sCisJeyAt
Njk4OSwgMjEsIDExfSwgeyAtNjk0OCwgMTEsIDEwfSwgeyAtNjkxMCwgMjMsIDExfSwgeyAtNjg3
MywgIDMsICA4fSwKKwl7IC02ODM3LCAyNSwgMTF9LCB7IC02ODAzLCAxMywgMTB9LCB7IC02Nzcw
LCAyNywgMTF9LCB7IC02NzM5LCAgNywgIDl9LAorCXsgLTY3MDgsIDI5LCAxMX0sIHsgLTY2Nzks
IDE1LCAxMH0sIHsgLTY2NTAsIDMxLCAxMX0sIHsgLTY2MjMsICAxLCAgNn0sCisJeyAtNjU3MCwg
MTcsIDEwfSwgeyAtNjUyMCwgIDksICA5fSwgeyAtNjQ3MywgMTksIDEwfSwgeyAtNjQyOSwgIDUs
ICA4fSwKKwl7IC02Mzg2LCAyMSwgMTB9LCB7IC02MzQ2LCAxMSwgIDl9LCB7IC02MzA3LCAyMywg
MTB9LCB7IC02MjcwLCAgMywgIDd9LAorCXsgLTYyMzUsIDI1LCAxMH0sIHsgLTYyMDEsIDEzLCAg
OX0sIHsgLTYxNjgsIDI3LCAxMH0sIHsgLTYxMzcsICA3LCAgOH0sCisJeyAtNjEwNiwgMjksIDEw
fSwgeyAtNjA3NywgMTUsICA5fSwgeyAtNjA0OCwgMzEsIDEwfSwgeyAtNjAyMSwgIDEsICA1fSwK
Kwl7IC01OTY4LCAxNywgIDl9LCB7IC01OTE4LCAgOSwgIDh9LCB7IC01ODcxLCAxOSwgIDl9LCB7
IC01ODI3LCAgNSwgIDd9LAorCXsgLTU3ODQsIDIxLCAgOX0sIHsgLTU3NDQsIDExLCAgOH0sIHsg
LTU3MDUsIDIzLCAgOX0sIHsgLTU2NjgsICAzLCAgNn0sCisJeyAtNTYzMywgMjUsICA5fSwgeyAt
NTU5OSwgMTMsICA4fSwgeyAtNTU2NiwgMjcsICA5fSwgeyAtNTUzNSwgIDcsICA3fSwKKwl7IC01
NTA0LCAyOSwgIDl9LCB7IC01NDc1LCAxNSwgIDh9LCB7IC01NDQ2LCAzMSwgIDl9LCB7IC01NDE5
LCAgMSwgIDR9LAorCXsgLTUzNjYsIDE3LCAgOH0sIHsgLTUzMTYsICA5LCAgN30sIHsgLTUyNjks
IDE5LCAgOH0sIHsgLTUyMjUsICA1LCAgNn0sCisJeyAtNTE4MiwgMjEsICA4fSwgeyAtNTE0Miwg
MTEsICA3fSwgeyAtNTEwMywgMjMsICA4fSwgeyAtNTA2NiwgIDMsICA1fSwKKwl7IC01MDMxLCAy
NSwgIDh9LCB7IC00OTk3LCAxMywgIDd9LCB7IC00OTY0LCAyNywgIDh9LCB7IC00OTMyLCAgNywg
IDZ9LAorCXsgLTQ5MDIsIDI5LCAgOH0sIHsgLTQ4NzMsIDE1LCAgN30sIHsgLTQ4NDQsIDMxLCAg
OH0sIHsgLTQ4MTYsICAxLCAgM30sCisJeyAtNDc2NCwgMTcsICA3fSwgeyAtNDcxNCwgIDksICA2
fSwgeyAtNDY2NywgMTksICA3fSwgeyAtNDYyMywgIDUsICA1fSwKKwl7IC00NTgwLCAyMSwgIDd9
LCB7IC00NTQwLCAxMSwgIDZ9LCB7IC00NTAxLCAyMywgIDd9LCB7IC00NDY0LCAgMywgIDR9LAor
CXsgLTQ0MjksIDI1LCAgN30sIHsgLTQzOTUsIDEzLCAgNn0sIHsgLTQzNjIsIDI3LCAgN30sIHsg
LTQzMzAsICA3LCAgNX0sCisJeyAtNDMwMCwgMjksICA3fSwgeyAtNDI3MCwgMTUsICA2fSwgeyAt
NDI0MiwgMzEsICA3fSwgeyAtNDIxNCwgIDEsICAyfSwKKwl7IC00MTYyLCAxNywgIDZ9LCB7IC00
MTEyLCAgOSwgIDV9LCB7IC00MDY1LCAxOSwgIDZ9LCB7IC00MDIxLCAgNSwgIDR9LAorCXsgLTM5
NzgsIDIxLCAgNn0sIHsgLTM5MzgsIDExLCAgNX0sIHsgLTM4OTksIDIzLCAgNn0sIHsgLTM4NjIs
ICAzLCAgM30sCisJeyAtMzgyNywgMjUsICA2fSwgeyAtMzc5MywgMTMsICA1fSwgeyAtMzc2MCwg
MjcsICA2fSwgeyAtMzcyOCwgIDcsICA0fSwKKwl7IC0zNjk4LCAyOSwgIDZ9LCB7IC0zNjY4LCAx
NSwgIDV9LCB7IC0zNjQwLCAzMSwgIDZ9LCB7IC0zNjEyLCAgMSwgIDF9LAorCXsgLTM1NjAsIDE3
LCAgNX0sIHsgLTM1MTAsICA5LCAgNH0sIHsgLTM0NjMsIDE5LCAgNX0sIHsgLTM0MTksICA1LCAg
M30sCisJeyAtMzM3NiwgMjEsICA1fSwgeyAtMzMzNiwgMTEsICA0fSwgeyAtMzI5NywgMjMsICA1
fSwgeyAtMzI2MCwgIDMsICAyfSwKKwl7IC0zMjI1LCAyNSwgIDV9LCB7IC0zMTkxLCAxMywgIDR9
LCB7IC0zMTU4LCAyNywgIDV9LCB7IC0zMTI2LCAgNywgIDN9LAorCXsgLTMwOTYsIDI5LCAgNX0s
IHsgLTMwNjYsIDE1LCAgNH0sIHsgLTMwMzgsIDMxLCAgNX0sIHsgLTMwMTAsICAxLCAgMH0sCisJ
eyAtMjk1OCwgMTcsICA0fSwgeyAtMjkwOCwgIDksICAzfSwgeyAtMjg2MSwgMTksICA0fSwgeyAt
MjgxNiwgIDUsICAyfSwKKwl7IC0yNzc0LCAyMSwgIDR9LCB7IC0yNzM0LCAxMSwgIDN9LCB7IC0y
Njk1LCAyMywgIDR9LCB7IC0yNjU4LCAgMywgIDF9LAorCXsgLTI2MjMsIDI1LCAgNH0sIHsgLTI1
ODksIDEzLCAgM30sIHsgLTI1NTYsIDI3LCAgNH0sIHsgLTI1MjQsICA3LCAgMn0sCisJeyAtMjQ5
NCwgMjksICA0fSwgeyAtMjQ2NCwgMTUsICAzfSwgeyAtMjQzNiwgMzEsICA0fSwgeyAtMjQwOCwg
IDIsICAwfSwKKwl7IC0yMzU2LCAxNywgIDN9LCB7IC0yMzA2LCAgOSwgIDJ9LCB7IC0yMjU5LCAx
OSwgIDN9LCB7IC0yMjE0LCAgNSwgIDF9LAorCXsgLTIxNzIsIDIxLCAgM30sIHsgLTIxMzIsIDEx
LCAgMn0sIHsgLTIwOTMsIDIzLCAgM30sIHsgLTIwNTYsICAzLCAgMH0sCisJeyAtMjAyMSwgMjUs
ICAzfSwgeyAtMTk4NywgMTMsICAyfSwgeyAtMTk1NCwgMjcsICAzfSwgeyAtMTkyMiwgIDcsICAx
fSwKKwl7IC0xODkyLCAyOSwgIDN9LCB7IC0xODYyLCAxNSwgIDJ9LCB7IC0xODM0LCAzMSwgIDN9
LCB7IC0xODA2LCAgNCwgIDB9LAorCXsgLTE3NTQsIDE3LCAgMn0sIHsgLTE3MDQsICA5LCAgMX0s
IHsgLTE2NTcsIDE5LCAgMn0sIHsgLTE2MTIsICA1LCAgMH0sCisJeyAtMTU3MCwgMjEsICAyfSwg
eyAtMTUzMCwgMTEsICAxfSwgeyAtMTQ5MSwgMjMsICAyfSwgeyAtMTQ1NCwgIDYsICAwfSwKKwl7
IC0xNDE5LCAyNSwgIDJ9LCB7IC0xMzg0LCAxMywgIDF9LCB7IC0xMzUyLCAyNywgIDJ9LCB7IC0x
MzIwLCAgNywgIDB9LAorCXsgLTEyOTAsIDI5LCAgMn0sIHsgLTEyNjAsIDE1LCAgMX0sIHsgLTEy
MzIsIDMxLCAgMn0sIHsgLTEyMDQsICA4LCAgMH0sCisJeyAtMTE1MSwgMTcsICAxfSwgeyAtMTEw
MiwgIDksICAwfSwgeyAtMTA1NSwgMTksICAxfSwgeyAtMTAxMCwgMTAsICAwfSwKKwl7ICAtOTY4
LCAyMSwgIDF9LCB7ICAtOTI4LCAxMSwgIDB9LCB7ICAtODg5LCAyMywgIDF9LCB7ICAtODUyLCAx
MiwgIDB9LAorCXsgIC04MTYsIDI1LCAgMX0sIHsgIC03ODIsIDEzLCAgMH0sIHsgIC03NTAsIDI3
LCAgMX0sIHsgIC03MTgsIDE0LCAgMH0sCisJeyAgLTY4OCwgMjksICAxfSwgeyAgLTY1OCwgMTUs
ICAwfSwgeyAgLTYzMCwgMzEsICAxfSwgeyAgLTYwMiwgMTYsICAwfSwKKwl7ICAtNTQ5LCAxNywg
IDB9LCB7ICAtNTAwLCAxOCwgIDB9LCB7ICAtNDUzLCAxOSwgIDB9LCB7ICAtNDA4LCAyMCwgIDB9
LAorCXsgIC0zNjYsIDIxLCAgMH0sIHsgIC0zMjUsIDIyLCAgMH0sIHsgIC0yODcsIDIzLCAgMH0s
IHsgIC0yNTAsIDI0LCAgMH0sCisJeyAgLTIxNCwgMjUsICAwfSwgeyAgLTE4MCwgMjYsICAwfSwg
eyAgLTE0OCwgMjcsICAwfSwgeyAgLTExNiwgMjgsICAwfSwKKwl7ICAgLTg2LCAyOSwgIDB9LCB7
ICAgLTU2LCAzMCwgIDB9LCB7ICAgLTI4LCAzMSwgIDB9LCB7ICAgICAwLCAgMCwgIDB9LAorfTsK
Kworc3RhdGljIGludCBwbTg2MHhfdm9sYXRpbGUodW5zaWduZWQgaW50IHJlZykKK3sKKwlCVUdf
T04ocmVnID49IFJFR19DQUNIRV9TSVpFKTsKKworCXN3aXRjaCAocmVnKSB7CisJY2FzZSBQTTg2
MFhfQVVESU9fU1VQUExJRVNfMjoKKwkJcmV0dXJuIDE7CisJfQorCisJcmV0dXJuIDA7Cit9CisK
K3N0YXRpYyB1bnNpZ25lZCBpbnQgcG04NjB4X3JlYWRfcmVnX2NhY2hlKHN0cnVjdCBzbmRfc29j
X2NvZGVjICpjb2RlYywKKwkJCQkJICB1bnNpZ25lZCBpbnQgcmVnKQoreworCXVuc2lnbmVkIGNo
YXIgKmNhY2hlID0gY29kZWMtPnJlZ19jYWNoZTsKKworCUJVR19PTihyZWcgPj0gUkVHX0NBQ0hF
X1NJWkUpOworCisJaWYgKHBtODYweF92b2xhdGlsZShyZWcpKQorCQlyZXR1cm4gY2FjaGVbcmVn
XTsKKworCXJlZyArPSBSRUdfQ0FDSEVfQkFTRTsKKworCXJldHVybiBwbTg2MHhfcmVnX3JlYWQo
Y29kZWMtPmNvbnRyb2xfZGF0YSwgcmVnKTsKK30KKworc3RhdGljIGludCBwbTg2MHhfd3JpdGVf
cmVnX2NhY2hlKHN0cnVjdCBzbmRfc29jX2NvZGVjICpjb2RlYywKKwkJCQkgIHVuc2lnbmVkIGlu
dCByZWcsIHVuc2lnbmVkIGludCB2YWx1ZSkKK3sKKwl1bnNpZ25lZCBjaGFyICpjYWNoZSA9IGNv
ZGVjLT5yZWdfY2FjaGU7CisKKwlCVUdfT04ocmVnID49IFJFR19DQUNIRV9TSVpFKTsKKworCWlm
ICghcG04NjB4X3ZvbGF0aWxlKHJlZykpCisJCWNhY2hlW3JlZ10gPSAodW5zaWduZWQgY2hhcil2
YWx1ZTsKKworCXJlZyArPSBSRUdfQ0FDSEVfQkFTRTsKKworCXJldHVybiBwbTg2MHhfcmVnX3dy
aXRlKGNvZGVjLT5jb250cm9sX2RhdGEsIHJlZywgdmFsdWUpOworfQorCitzdGF0aWMgaW50IHNu
ZF9zb2NfZ2V0X3ZvbHN3XzJyX3N0KHN0cnVjdCBzbmRfa2NvbnRyb2wgKmtjb250cm9sLAorCQkJ
CSAgIHN0cnVjdCBzbmRfY3RsX2VsZW1fdmFsdWUgKnVjb250cm9sKQoreworCXN0cnVjdCBzb2Nf
bWl4ZXJfY29udHJvbCAqbWMgPQorCQkoc3RydWN0IHNvY19taXhlcl9jb250cm9sICopa2NvbnRy
b2wtPnByaXZhdGVfdmFsdWU7CisJc3RydWN0IHNuZF9zb2NfY29kZWMgKmNvZGVjID0gc25kX2tj
b250cm9sX2NoaXAoa2NvbnRyb2wpOworCXVuc2lnbmVkIGludCByZWcgPSBtYy0+cmVnOworCXVu
c2lnbmVkIGludCByZWcyID0gbWMtPnJyZWc7CisJaW50IHZhbFsyXSwgdmFsMlsyXSwgaTsKKwor
CXZhbFswXSA9IHNuZF9zb2NfcmVhZChjb2RlYywgcmVnKSAmIDB4M2Y7CisJdmFsWzFdID0gKHNu
ZF9zb2NfcmVhZChjb2RlYywgUE04NjBYX1NJREVUT05FX1NISUZUKSA+PiA0KSAmIDB4ZjsKKwl2
YWwyWzBdID0gc25kX3NvY19yZWFkKGNvZGVjLCByZWcyKSAmIDB4M2Y7CisJdmFsMlsxXSA9IChz
bmRfc29jX3JlYWQoY29kZWMsIFBNODYwWF9TSURFVE9ORV9TSElGVCkpICYgMHhmOworCisJZm9y
IChpID0gMDsgaSA8IEFSUkFZX1NJWkUoc3RfdGFibGUpOyBpKyspIHsKKwkJaWYgKChzdF90YWJs
ZVtpXS5tID09IHZhbFswXSkgJiYgKHN0X3RhYmxlW2ldLm4gPT0gdmFsWzFdKSkKKwkJCXVjb250
cm9sLT52YWx1ZS5pbnRlZ2VyLnZhbHVlWzBdID0gaTsKKwkJaWYgKChzdF90YWJsZVtpXS5tID09
IHZhbDJbMF0pICYmIChzdF90YWJsZVtpXS5uID09IHZhbDJbMV0pKQorCQkJdWNvbnRyb2wtPnZh
bHVlLmludGVnZXIudmFsdWVbMV0gPSBpOworCX0KKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGlu
dCBzbmRfc29jX3B1dF92b2xzd18ycl9zdChzdHJ1Y3Qgc25kX2tjb250cm9sICprY29udHJvbCwK
KwkJCQkgICBzdHJ1Y3Qgc25kX2N0bF9lbGVtX3ZhbHVlICp1Y29udHJvbCkKK3sKKwlzdHJ1Y3Qg
c29jX21peGVyX2NvbnRyb2wgKm1jID0KKwkJKHN0cnVjdCBzb2NfbWl4ZXJfY29udHJvbCAqKWtj
b250cm9sLT5wcml2YXRlX3ZhbHVlOworCXN0cnVjdCBzbmRfc29jX2NvZGVjICpjb2RlYyA9IHNu
ZF9rY29udHJvbF9jaGlwKGtjb250cm9sKTsKKwl1bnNpZ25lZCBpbnQgcmVnID0gbWMtPnJlZzsK
Kwl1bnNpZ25lZCBpbnQgcmVnMiA9IG1jLT5ycmVnOworCWludCBlcnI7CisJdW5zaWduZWQgaW50
IHZhbCwgdmFsMjsKKworCXZhbCA9IHVjb250cm9sLT52YWx1ZS5pbnRlZ2VyLnZhbHVlWzBdOwor
CXZhbDIgPSB1Y29udHJvbC0+dmFsdWUuaW50ZWdlci52YWx1ZVsxXTsKKworCWVyciA9IHNuZF9z
b2NfdXBkYXRlX2JpdHMoY29kZWMsIHJlZywgMHgzZiwgc3RfdGFibGVbdmFsXS5tKTsKKwlpZiAo
ZXJyIDwgMCkKKwkJcmV0dXJuIGVycjsKKwllcnIgPSBzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVj
LCBQTTg2MFhfU0lERVRPTkVfU0hJRlQsIDB4ZjAsCisJCQkJICBzdF90YWJsZVt2YWxdLm4gPDwg
NCk7CisJaWYgKGVyciA8IDApCisJCXJldHVybiBlcnI7CisKKwllcnIgPSBzbmRfc29jX3VwZGF0
ZV9iaXRzKGNvZGVjLCByZWcyLCAweDNmLCBzdF90YWJsZVt2YWwyXS5tKTsKKwlpZiAoZXJyIDwg
MCkKKwkJcmV0dXJuIGVycjsKKwllcnIgPSBzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVjLCBQTTg2
MFhfU0lERVRPTkVfU0hJRlQsIDB4MGYsCisJCQkJICBzdF90YWJsZVt2YWwyXS5uKTsKKwlyZXR1
cm4gZXJyOworfQorCitzdGF0aWMgaW50IHNuZF9zb2NfZ2V0X3ZvbHN3XzJyX291dChzdHJ1Y3Qg
c25kX2tjb250cm9sICprY29udHJvbCwKKwkJCQkgICAgc3RydWN0IHNuZF9jdGxfZWxlbV92YWx1
ZSAqdWNvbnRyb2wpCit7CisJc3RydWN0IHNvY19taXhlcl9jb250cm9sICptYyA9CisJCShzdHJ1
Y3Qgc29jX21peGVyX2NvbnRyb2wgKilrY29udHJvbC0+cHJpdmF0ZV92YWx1ZTsKKwlzdHJ1Y3Qg
c25kX3NvY19jb2RlYyAqY29kZWMgPSBzbmRfa2NvbnRyb2xfY2hpcChrY29udHJvbCk7CisJdW5z
aWduZWQgaW50IHJlZyA9IG1jLT5yZWc7CisJdW5zaWduZWQgaW50IHJlZzIgPSBtYy0+cnJlZzsK
Kwl1bnNpZ25lZCBpbnQgc2hpZnQgPSBtYy0+c2hpZnQ7CisJaW50IG1heCA9IG1jLT5tYXgsIHZh
bCwgdmFsMjsKKwl1bnNpZ25lZCBpbnQgbWFzayA9ICgxIDw8IGZscyhtYXgpKSAtIDE7CisKKwl2
YWwgPSBzbmRfc29jX3JlYWQoY29kZWMsIHJlZykgPj4gc2hpZnQ7CisJdmFsMiA9IHNuZF9zb2Nf
cmVhZChjb2RlYywgcmVnMikgPj4gc2hpZnQ7CisJdWNvbnRyb2wtPnZhbHVlLmludGVnZXIudmFs
dWVbMF0gPSAobWF4IC0gdmFsKSAmIG1hc2s7CisJdWNvbnRyb2wtPnZhbHVlLmludGVnZXIudmFs
dWVbMV0gPSAobWF4IC0gdmFsMikgJiBtYXNrOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBp
bnQgc25kX3NvY19wdXRfdm9sc3dfMnJfb3V0KHN0cnVjdCBzbmRfa2NvbnRyb2wgKmtjb250cm9s
LAorCQkJCSAgICBzdHJ1Y3Qgc25kX2N0bF9lbGVtX3ZhbHVlICp1Y29udHJvbCkKK3sKKwlzdHJ1
Y3Qgc29jX21peGVyX2NvbnRyb2wgKm1jID0KKwkJKHN0cnVjdCBzb2NfbWl4ZXJfY29udHJvbCAq
KWtjb250cm9sLT5wcml2YXRlX3ZhbHVlOworCXN0cnVjdCBzbmRfc29jX2NvZGVjICpjb2RlYyA9
IHNuZF9rY29udHJvbF9jaGlwKGtjb250cm9sKTsKKwl1bnNpZ25lZCBpbnQgcmVnID0gbWMtPnJl
ZzsKKwl1bnNpZ25lZCBpbnQgcmVnMiA9IG1jLT5ycmVnOworCXVuc2lnbmVkIGludCBzaGlmdCA9
IG1jLT5zaGlmdDsKKwlpbnQgbWF4ID0gbWMtPm1heDsKKwl1bnNpZ25lZCBpbnQgbWFzayA9ICgx
IDw8IGZscyhtYXgpKSAtIDE7CisJaW50IGVycjsKKwl1bnNpZ25lZCBpbnQgdmFsLCB2YWwyLCB2
YWxfbWFzazsKKworCXZhbF9tYXNrID0gbWFzayA8PCBzaGlmdDsKKwl2YWwgPSAoKG1heCAtIHVj
b250cm9sLT52YWx1ZS5pbnRlZ2VyLnZhbHVlWzBdKSAmIG1hc2spOworCXZhbDIgPSAoKG1heCAt
IHVjb250cm9sLT52YWx1ZS5pbnRlZ2VyLnZhbHVlWzFdKSAmIG1hc2spOworCisJdmFsID0gdmFs
IDw8IHNoaWZ0OworCXZhbDIgPSB2YWwyIDw8IHNoaWZ0OworCisJZXJyID0gc25kX3NvY191cGRh
dGVfYml0cyhjb2RlYywgcmVnLCB2YWxfbWFzaywgdmFsKTsKKwlpZiAoZXJyIDwgMCkKKwkJcmV0
dXJuIGVycjsKKworCWVyciA9IHNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIHJlZzIsIHZhbF9t
YXNrLCB2YWwyKTsKKwlyZXR1cm4gZXJyOworfQorCisvKiBEQVBNIFdpZGdldCBFdmVudHMgKi8K
K3N0YXRpYyBpbnQgcG04NjB4X3JzeW5jX2V2ZW50KHN0cnVjdCBzbmRfc29jX2RhcG1fd2lkZ2V0
ICp3LAorCQkJICAgICAgc3RydWN0IHNuZF9rY29udHJvbCAqa2NvbnRyb2wsIGludCBldmVudCkK
K3sKKwlzdHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWMgPSB3LT5jb2RlYzsKKworCS8qIHVubXV0
ZSBEQUMgKi8KKwlzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVjLCBQTTg2MFhfREFDX09GRlNFVCwg
REFDX01VVEUsIDApOworCXNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9FQVJfQ1RS
TF8yLAorCQkJICAgIFJTWU5DX0NIQU5HRSwgUlNZTkNfQ0hBTkdFKTsKKwlyZXR1cm4gMDsKK30K
Kworc3RhdGljIGludCBwbTg2MHhfYWRjX2V2ZW50KHN0cnVjdCBzbmRfc29jX2RhcG1fd2lkZ2V0
ICp3LAorCQkJICAgIHN0cnVjdCBzbmRfa2NvbnRyb2wgKmtjb250cm9sLCBpbnQgZXZlbnQpCit7
CisJc3RydWN0IHNuZF9zb2NfY29kZWMgKmNvZGVjID0gdy0+Y29kZWM7CisJdW5zaWduZWQgaW50
IGVuMSA9IDAsIGVuMiA9IDA7CisKKwlpZiAoIXN0cmNtcCh3LT5uYW1lLCAiTGVmdCBBREMiKSkg
eworCQllbjEgPSBBRENfTU9EX0xFRlQ7CisJCWVuMiA9IEFEQ19MRUZUOworCX0KKwlpZiAoIXN0
cmNtcCh3LT5uYW1lLCAiUmlnaHQgQURDIikpIHsKKwkJZW4xID0gQURDX01PRF9SSUdIVDsKKwkJ
ZW4yID0gQURDX1JJR0hUOworCX0KKwlzd2l0Y2ggKGV2ZW50KSB7CisJY2FzZSBTTkRfU09DX0RB
UE1fUFJFX1BNVToKKwkJc25kX3NvY191cGRhdGVfYml0cyhjb2RlYywgUE04NjBYX0FEQ19FTl8x
LCBlbjEsIGVuMSk7CisJCXNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9BRENfRU5f
MiwgZW4yLCBlbjIpOworCQlicmVhazsKKwljYXNlIFNORF9TT0NfREFQTV9QUkVfUE1EOgorCQlz
bmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVjLCBQTTg2MFhfQURDX0VOXzEsIGVuMSwgMCk7CisJCXNu
ZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9BRENfRU5fMiwgZW4yLCAwKTsKKwkJYnJl
YWs7CisJfQorCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHBtODYweF9kYWNfZXZlbnQoc3Ry
dWN0IHNuZF9zb2NfZGFwbV93aWRnZXQgKncsCisJCQkgICAgc3RydWN0IHNuZF9rY29udHJvbCAq
a2NvbnRyb2wsIGludCBldmVudCkKK3sKKwlzdHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWMgPSB3
LT5jb2RlYzsKKwl1bnNpZ25lZCBpbnQgZGFjID0gMDsKKwlpbnQgZGF0YTsKKworCWlmICghc3Ry
Y21wKHctPm5hbWUsICJMZWZ0IERBQyIpKQorCQlkYWMgPSBEQUNfTEVGVDsKKwlpZiAoIXN0cmNt
cCh3LT5uYW1lLCAiUmlnaHQgREFDIikpCisJCWRhYyA9IERBQ19SSUdIVDsKKwlzd2l0Y2ggKGV2
ZW50KSB7CisJY2FzZSBTTkRfU09DX0RBUE1fUFJFX1BNVToKKwkJaWYgKGRhYykgeworCQkJZGFj
IHw9IE1PRFVMQVRPUjsKKwkJCS8qIG11dGUgKi8KKwkJCXNuZF9zb2NfdXBkYXRlX2JpdHMoY29k
ZWMsIFBNODYwWF9EQUNfT0ZGU0VULAorCQkJCQkgICAgREFDX01VVEUsIERBQ19NVVRFKTsKKwkJ
CXNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9FQVJfQ1RSTF8yLAorCQkJCQkgICAg
UlNZTkNfQ0hBTkdFLCBSU1lOQ19DSEFOR0UpOworCQkJLyogdXBkYXRlIGRhYyAqLworCQkJc25k
X3NvY191cGRhdGVfYml0cyhjb2RlYywgUE04NjBYX0RBQ19FTl8yLAorCQkJCQkgICAgZGFjLCBk
YWMpOworCQl9CisJCWJyZWFrOworCWNhc2UgU05EX1NPQ19EQVBNX1BSRV9QTUQ6CisJCWlmIChk
YWMpIHsKKwkJCS8qIG11dGUgKi8KKwkJCXNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYw
WF9EQUNfT0ZGU0VULAorCQkJCQkgICAgREFDX01VVEUsIERBQ19NVVRFKTsKKwkJCXNuZF9zb2Nf
dXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9FQVJfQ1RSTF8yLAorCQkJCQkgICAgUlNZTkNfQ0hB
TkdFLCBSU1lOQ19DSEFOR0UpOworCQkJLyogdXBkYXRlIGRhYyAqLworCQkJZGF0YSA9IHNuZF9z
b2NfcmVhZChjb2RlYywgUE04NjBYX0RBQ19FTl8yKTsKKwkJCWRhdGEgJj0gfmRhYzsKKwkJCWlm
ICghKGRhdGEgJiAoREFDX0xFRlQgfCBEQUNfUklHSFQpKSkKKwkJCQlkYXRhICY9IH5NT0RVTEFU
T1I7CisJCQlzbmRfc29jX3dyaXRlKGNvZGVjLCBQTTg2MFhfREFDX0VOXzIsIGRhdGEpOworCQl9
CisJCWJyZWFrOworCX0KKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBwbTg2MHhfbWljMV9l
dmVudChzdHJ1Y3Qgc25kX3NvY19kYXBtX3dpZGdldCAqdywKKwkJCSAgICAgc3RydWN0IHNuZF9r
Y29udHJvbCAqa2NvbnRyb2wsIGludCBldmVudCkKK3sKKwlzdHJ1Y3Qgc25kX3NvY19jb2RlYyAq
Y29kZWMgPSB3LT5jb2RlYzsKKworCXN3aXRjaCAoZXZlbnQpIHsKKwljYXNlIFNORF9TT0NfREFQ
TV9QT1NUX1BNVToKKwkJLyogRW5hYmxlIE1pYzEgQmlhcyAmIE1JQ0RFVCwgSFNERVQgKi8KKwkJ
c25kX3NvY191cGRhdGVfYml0cyhjb2RlYywgUE04NjBYX0FEQ19BTkFfMSwgTUlDMUJJQVNfTUFT
SywKKwkJCQkgICAgTUlDMUJJQVNfTUFTSyk7CisJCXBtODYweF9zZXRfYml0cyhjb2RlYy0+Y29u
dHJvbF9kYXRhLCBSRUdfTUlDX0RFVCwKKwkJCQlNSUNERVRfTUFTSywgTUlDREVUX01BU0spOwor
CQlwbTg2MHhfc2V0X2JpdHMoY29kZWMtPmNvbnRyb2xfZGF0YSwgUkVHX0hTX0RFVCwKKwkJCQlF
Tl9IU19ERVQsIEVOX0hTX0RFVCk7CisJCWJyZWFrOworCWNhc2UgU05EX1NPQ19EQVBNX1BSRV9Q
TUQ6CisJCS8qIGRpc2FibGUgTWljMSBCaWFzICYgTUlDREVULCBIU0RFVCAqLworCQlwbTg2MHhf
c2V0X2JpdHMoY29kZWMtPmNvbnRyb2xfZGF0YSwgUkVHX01JQ19ERVQsCisJCQkJTUlDREVUX01B
U0ssIDApOworCQlwbTg2MHhfc2V0X2JpdHMoY29kZWMtPmNvbnRyb2xfZGF0YSwgUkVHX0hTX0RF
VCwKKwkJCQlFTl9IU19ERVQsIDApOworCQlzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVjLCBQTTg2
MFhfQURDX0FOQV8xLCBNSUMxQklBU19NQVNLLCAwKTsKKwkJYnJlYWs7CisJfQorCXJldHVybiAw
OworfQorCitzdGF0aWMgY29uc3QgY2hhciAqcG04NjB4X29wYW1wX3RleHRzW10gPSB7Ii01MCUi
LCAiLTI1JSIsICIwJSIsICI3NSUifTsKKworc3RhdGljIGNvbnN0IGNoYXIgKnBtODYweF9wYV90
ZXh0c1tdID0geyItMzMlIiwgIjAlIiwgIjMzJSIsICI2NiUifTsKKworc3RhdGljIGNvbnN0IHN0
cnVjdCBzb2NfZW51bSBwbTg2MHhfaHMxX29wYW1wX2VudW0gPQorCVNPQ19FTlVNX1NJTkdMRShQ
TTg2MFhfSFMxX0NUUkwsIDUsIDQsIHBtODYweF9vcGFtcF90ZXh0cyk7CisKK3N0YXRpYyBjb25z
dCBzdHJ1Y3Qgc29jX2VudW0gcG04NjB4X2hzMl9vcGFtcF9lbnVtID0KKwlTT0NfRU5VTV9TSU5H
TEUoUE04NjBYX0hTMl9DVFJMLCA1LCA0LCBwbTg2MHhfb3BhbXBfdGV4dHMpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNvY19lbnVtIHBtODYweF9oczFfcGFfZW51bSA9CisJU09DX0VOVU1fU0lO
R0xFKFBNODYwWF9IUzFfQ1RSTCwgMywgNCwgcG04NjB4X3BhX3RleHRzKTsKKworc3RhdGljIGNv
bnN0IHN0cnVjdCBzb2NfZW51bSBwbTg2MHhfaHMyX3BhX2VudW0gPQorCVNPQ19FTlVNX1NJTkdM
RShQTTg2MFhfSFMyX0NUUkwsIDMsIDQsIHBtODYweF9wYV90ZXh0cyk7CisKK3N0YXRpYyBjb25z
dCBzdHJ1Y3Qgc29jX2VudW0gcG04NjB4X2xvMV9vcGFtcF9lbnVtID0KKwlTT0NfRU5VTV9TSU5H
TEUoUE04NjBYX0xPMV9DVFJMLCA1LCA0LCBwbTg2MHhfb3BhbXBfdGV4dHMpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNvY19lbnVtIHBtODYweF9sbzJfb3BhbXBfZW51bSA9CisJU09DX0VOVU1f
U0lOR0xFKFBNODYwWF9MTzJfQ1RSTCwgNSwgNCwgcG04NjB4X29wYW1wX3RleHRzKTsKKworc3Rh
dGljIGNvbnN0IHN0cnVjdCBzb2NfZW51bSBwbTg2MHhfbG8xX3BhX2VudW0gPQorCVNPQ19FTlVN
X1NJTkdMRShQTTg2MFhfTE8xX0NUUkwsIDMsIDQsIHBtODYweF9wYV90ZXh0cyk7CisKK3N0YXRp
YyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gcG04NjB4X2xvMl9wYV9lbnVtID0KKwlTT0NfRU5VTV9T
SU5HTEUoUE04NjBYX0xPMl9DVFJMLCAzLCA0LCBwbTg2MHhfcGFfdGV4dHMpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNvY19lbnVtIHBtODYweF9zcGtfcGFfZW51bSA9CisJU09DX0VOVU1fU0lO
R0xFKFBNODYwWF9FQVJfQ1RSTF8xLCA1LCA0LCBwbTg2MHhfcGFfdGV4dHMpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNvY19lbnVtIHBtODYweF9lYXJfcGFfZW51bSA9CisJU09DX0VOVU1fU0lO
R0xFKFBNODYwWF9FQVJfQ1RSTF8yLCAwLCA0LCBwbTg2MHhfcGFfdGV4dHMpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNvY19lbnVtIHBtODYweF9zcGtfZWFyX29wYW1wX2VudW0gPQorCVNPQ19F
TlVNX1NJTkdMRShQTTg2MFhfRUFSX0NUUkxfMSwgMywgNCwgcG04NjB4X29wYW1wX3RleHRzKTsK
Kworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IHBtODYweF9zbmRfY29udHJv
bHNbXSA9IHsKKwlTT0NfRE9VQkxFX1JfVExWKCJBREMgQ2FwdHVyZSBWb2x1bWUiLCBQTTg2MFhf
QURDX0FOQV8yLAorCQkJUE04NjBYX0FEQ19BTkFfMywgNiwgMywgMCwgYWRjX3RsdiksCisJU09D
X0RPVUJMRV9UTFYoIkFVWCBDYXB0dXJlIFZvbHVtZSIsIFBNODYwWF9BRENfQU5BXzMsIDAsIDMs
IDcsIDAsCisJCQlhdXhfdGx2KSwKKwlTT0NfU0lOR0xFX1RMVigiTUlDMSBDYXB0dXJlIFZvbHVt
ZSIsIFBNODYwWF9BRENfQU5BXzIsIDAsIDcsIDAsCisJCQltaWNfdGx2KSwKKwlTT0NfU0lOR0xF
X1RMVigiTUlDMyBDYXB0dXJlIFZvbHVtZSIsIFBNODYwWF9BRENfQU5BXzIsIDMsIDcsIDAsCisJ
CQltaWNfdGx2KSwKKwlTT0NfRE9VQkxFX1JfRVhUX1RMVigiU2lkZXRvbmUgVm9sdW1lIiwgUE04
NjBYX1NJREVUT05FX0xfR0FJTiwKKwkJCSAgICAgUE04NjBYX1NJREVUT05FX1JfR0FJTiwgMCwg
QVJSQVlfU0laRShzdF90YWJsZSktMSwKKwkJCSAgICAgMCwgc25kX3NvY19nZXRfdm9sc3dfMnJf
c3QsCisJCQkgICAgIHNuZF9zb2NfcHV0X3ZvbHN3XzJyX3N0LCBzdF90bHYpLAorCVNPQ19TSU5H
TEVfVExWKCJTcGVha2VyIFBsYXliYWNrIFZvbHVtZSIsIFBNODYwWF9FQVJfQ1RSTF8xLAorCQkJ
MCwgNywgMCwgb3V0X3RsdiksCisJU09DX0RPVUJMRV9SX1RMVigiTGluZSBQbGF5YmFjayBWb2x1
bWUiLCBQTTg2MFhfTE8xX0NUUkwsCisJCQkgUE04NjBYX0xPMl9DVFJMLCAwLCA3LCAwLCBvdXRf
dGx2KSwKKwlTT0NfRE9VQkxFX1JfVExWKCJIZWFkc2V0IFBsYXliYWNrIFZvbHVtZSIsIFBNODYw
WF9IUzFfQ1RSTCwKKwkJCSBQTTg2MFhfSFMyX0NUUkwsIDAsIDcsIDAsIG91dF90bHYpLAorCVNP
Q19ET1VCTEVfUl9FWFRfVExWKCJIaWZpIExlZnQgUGxheWJhY2sgVm9sdW1lIiwKKwkJCSAgICAg
UE04NjBYX0hJRklMX0dBSU5fTEVGVCwKKwkJCSAgICAgUE04NjBYX0hJRklMX0dBSU5fUklHSFQs
IDAsIDYzLCAwLAorCQkJICAgICBzbmRfc29jX2dldF92b2xzd18ycl9vdXQsCisJCQkgICAgIHNu
ZF9zb2NfcHV0X3ZvbHN3XzJyX291dCwgZHBnYV90bHYpLAorCVNPQ19ET1VCTEVfUl9FWFRfVExW
KCJIaWZpIFJpZ2h0IFBsYXliYWNrIFZvbHVtZSIsCisJCQkgICAgIFBNODYwWF9ISUZJUl9HQUlO
X0xFRlQsCisJCQkgICAgIFBNODYwWF9ISUZJUl9HQUlOX1JJR0hULCAwLCA2MywgMCwKKwkJCSAg
ICAgc25kX3NvY19nZXRfdm9sc3dfMnJfb3V0LAorCQkJICAgICBzbmRfc29jX3B1dF92b2xzd18y
cl9vdXQsIGRwZ2FfdGx2KSwKKwlTT0NfRE9VQkxFX1JfRVhUX1RMVigiTG9maSBQbGF5YmFjayBW
b2x1bWUiLCBQTTg2MFhfTE9GSV9HQUlOX0xFRlQsCisJCQkgICAgIFBNODYwWF9MT0ZJX0dBSU5f
UklHSFQsIDAsIDYzLCAwLAorCQkJICAgICBzbmRfc29jX2dldF92b2xzd18ycl9vdXQsCisJCQkg
ICAgIHNuZF9zb2NfcHV0X3ZvbHN3XzJyX291dCwgZHBnYV90bHYpLAorCVNPQ19FTlVNKCJIZWFk
c2V0MSBPcGVyYXRpb25hbCBBbXBsaWZpZXIgQ3VycmVudCIsCisJCSBwbTg2MHhfaHMxX29wYW1w
X2VudW0pLAorCVNPQ19FTlVNKCJIZWFkc2V0MiBPcGVyYXRpb25hbCBBbXBsaWZpZXIgQ3VycmVu
dCIsCisJCSBwbTg2MHhfaHMyX29wYW1wX2VudW0pLAorCVNPQ19FTlVNKCJIZWFkc2V0MSBBbXBs
aWZpZXIgQ3VycmVudCIsIHBtODYweF9oczFfcGFfZW51bSksCisJU09DX0VOVU0oIkhlYWRzZXQy
IEFtcGxpZmllciBDdXJyZW50IiwgcG04NjB4X2hzMl9wYV9lbnVtKSwKKwlTT0NfRU5VTSgiTGlu
ZW91dDEgT3BlcmF0aW9uYWwgQW1wbGlmaWVyIEN1cnJlbnQiLAorCQkgcG04NjB4X2xvMV9vcGFt
cF9lbnVtKSwKKwlTT0NfRU5VTSgiTGluZW91dDIgT3BlcmF0aW9uYWwgQW1wbGlmaWVyIEN1cnJl
bnQiLAorCQkgcG04NjB4X2xvMl9vcGFtcF9lbnVtKSwKKwlTT0NfRU5VTSgiTGluZW91dDEgQW1w
bGlmaWVyIEN1cnJlbnQiLCBwbTg2MHhfbG8xX3BhX2VudW0pLAorCVNPQ19FTlVNKCJMaW5lb3V0
MiBBbXBsaWZpZXIgQ3VycmVudCIsIHBtODYweF9sbzJfcGFfZW51bSksCisJU09DX0VOVU0oIlNw
ZWFrZXIgT3BlcmF0aW9uYWwgQW1wbGlmaWVyIEN1cnJlbnQiLAorCQkgcG04NjB4X3Nwa19lYXJf
b3BhbXBfZW51bSksCisJU09DX0VOVU0oIlNwZWFrZXIgQW1wbGlmaWVyIEN1cnJlbnQiLCBwbTg2
MHhfc3BrX3BhX2VudW0pLAorCVNPQ19FTlVNKCJFYXJwaWVjZSBBbXBsaWZpZXIgQ3VycmVudCIs
IHBtODYweF9lYXJfcGFfZW51bSksCit9OworCisvKgorICogREFQTSBDb250cm9scworICovCisK
Ky8qIFBDTSBTd2l0Y2ggLyBQQ00gSW50ZXJmYWNlICovCitzdGF0aWMgY29uc3Qgc3RydWN0IHNu
ZF9rY29udHJvbF9uZXcgcGNtX3N3aXRjaF9jb250cm9scyA9CisJU09DX0RBUE1fU0lOR0xFKCJT
d2l0Y2giLCBQTTg2MFhfQURDX0VOXzIsIDAsIDEsIDApOworCisvKiBBVVgxIFN3aXRjaCAqLwor
c3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGF1eDFfc3dpdGNoX2NvbnRyb2xz
ID0KKwlTT0NfREFQTV9TSU5HTEUoIlN3aXRjaCIsIFBNODYwWF9BTkFfVE9fQU5BLCA0LCAxLCAw
KTsKKworLyogQVVYMiBTd2l0Y2ggKi8KK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX2tjb250cm9s
X25ldyBhdXgyX3N3aXRjaF9jb250cm9scyA9CisJU09DX0RBUE1fU0lOR0xFKCJTd2l0Y2giLCBQ
TTg2MFhfQU5BX1RPX0FOQSwgNSwgMSwgMCk7CisKKy8qIExlZnQgRXguIFBBIFN3aXRjaCAqLwor
c3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGxlcGFfc3dpdGNoX2NvbnRyb2xz
ID0KKwlTT0NfREFQTV9TSU5HTEUoIlN3aXRjaCIsIFBNODYwWF9EQUNfRU5fMiwgMiwgMSwgMCk7
CisKKy8qIFJpZ2h0IEV4LiBQQSBTd2l0Y2ggKi8KK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX2tj
b250cm9sX25ldyByZXBhX3N3aXRjaF9jb250cm9scyA9CisJU09DX0RBUE1fU0lOR0xFKCJTd2l0
Y2giLCBQTTg2MFhfREFDX0VOXzIsIDEsIDEsIDApOworCisvKiBQQ00gTXV4IC8gTXV4NyAqLwor
c3RhdGljIGNvbnN0IGNoYXIgKmFpZjFfdGV4dFtdID0geworCSJQQ00gTCIsICJQQ00gUiIsCit9
OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIGFpZjFfZW51bSA9CisJU09DX0VOVU1f
U0lOR0xFKFBNODYwWF9QQ01fSUZBQ0VfMywgNiwgMiwgYWlmMV90ZXh0KTsKKworc3RhdGljIGNv
bnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGFpZjFfbXV4ID0KKwlTT0NfREFQTV9FTlVNKCJQ
Q00gTXV4IiwgYWlmMV9lbnVtKTsKKworLyogSTJTIE11eCAvIE11eDkgKi8KK3N0YXRpYyBjb25z
dCBjaGFyICppMnNfZGluX3RleHRbXSA9IHsKKwkiRElOIiwgIkRJTjEiLAorfTsKKworc3RhdGlj
IGNvbnN0IHN0cnVjdCBzb2NfZW51bSBpMnNfZGluX2VudW0gPQorCVNPQ19FTlVNX1NJTkdMRShQ
TTg2MFhfSTJTX0lGQUNFXzMsIDEsIDIsIGkyc19kaW5fdGV4dCk7CisKK3N0YXRpYyBjb25zdCBz
dHJ1Y3Qgc25kX2tjb250cm9sX25ldyBpMnNfZGluX211eCA9CisJU09DX0RBUE1fRU5VTSgiSTJT
IERJTiBNdXgiLCBpMnNfZGluX2VudW0pOworCisvKiBJMlMgTWljIE11eCAvIE11eDggKi8KK3N0
YXRpYyBjb25zdCBjaGFyICppMnNfbWljX3RleHRbXSA9IHsKKwkiRXggUEEiLCAiQURDIiwKK307
CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gaTJzX21pY19lbnVtID0KKwlTT0NfRU5V
TV9TSU5HTEUoUE04NjBYX0kyU19JRkFDRV8zLCA0LCAyLCBpMnNfbWljX3RleHQpOworCitzdGF0
aWMgY29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgaTJzX21pY19tdXggPQorCVNPQ19EQVBN
X0VOVU0oIkkyUyBNaWMgTXV4IiwgaTJzX21pY19lbnVtKTsKKworLyogQURDTCBNdXggLyBNdXgy
ICovCitzdGF0aWMgY29uc3QgY2hhciAqYWRjbF90ZXh0W10gPSB7CisJIkFEQ1IiLCAiQURDTCIs
Cit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIGFkY2xfZW51bSA9CisJU09DX0VO
VU1fU0lOR0xFKFBNODYwWF9QQ01fSUZBQ0VfMywgNCwgMiwgYWRjbF90ZXh0KTsKKworc3RhdGlj
IGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGFkY2xfbXV4ID0KKwlTT0NfREFQTV9FTlVN
KCJBREMgTGVmdCBNdXgiLCBhZGNsX2VudW0pOworCisvKiBBRENSIE11eCAvIE11eDMgKi8KK3N0
YXRpYyBjb25zdCBjaGFyICphZGNyX3RleHRbXSA9IHsKKwkiQURDTCIsICJBRENSIiwKK307CisK
K3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gYWRjcl9lbnVtID0KKwlTT0NfRU5VTV9TSU5H
TEUoUE04NjBYX1BDTV9JRkFDRV8zLCAyLCAyLCBhZGNyX3RleHQpOworCitzdGF0aWMgY29uc3Qg
c3RydWN0IHNuZF9rY29udHJvbF9uZXcgYWRjcl9tdXggPQorCVNPQ19EQVBNX0VOVU0oIkFEQyBS
aWdodCBNdXgiLCBhZGNyX2VudW0pOworCisvKiBBRENSIEVDIE11eCAvIE11eDYgKi8KK3N0YXRp
YyBjb25zdCBjaGFyICphZGNyX2VjX3RleHRbXSA9IHsKKwkiQURDUiIsICJFQyIsCit9OworCitz
dGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIGFkY3JfZWNfZW51bSA9CisJU09DX0VOVU1fU0lO
R0xFKFBNODYwWF9BRENfRU5fMiwgMywgMiwgYWRjcl9lY190ZXh0KTsKKworc3RhdGljIGNvbnN0
IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGFkY3JfZWNfbXV4ID0KKwlTT0NfREFQTV9FTlVNKCJB
RENSIEVDIE11eCIsIGFkY3JfZWNfZW51bSk7CisKKy8qIEVDIE11eCAvIE11eDQgKi8KK3N0YXRp
YyBjb25zdCBjaGFyICplY190ZXh0W10gPSB7CisJIkxlZnQiLCAiUmlnaHQiLCAiTGVmdCArIFJp
Z2h0IiwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gZWNfZW51bSA9CisJU09D
X0VOVU1fU0lOR0xFKFBNODYwWF9FQ19QQVRILCAxLCAzLCBlY190ZXh0KTsKKworc3RhdGljIGNv
bnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGVjX211eCA9CisJU09DX0RBUE1fRU5VTSgiRUMg
TXV4IiwgZWNfZW51bSk7CisKK3N0YXRpYyBjb25zdCBjaGFyICpkYWNfdGV4dFtdID0geworCSJO
byBpbnB1dCIsICJSaWdodCIsICJMZWZ0IiwgIk5vIGlucHV0IiwKK307CisKKy8qIERBQyBIZWFk
c2V0IDEgTXV4IC8gTXV4MTAgKi8KK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gZGFjX2hz
MV9lbnVtID0KKwlTT0NfRU5VTV9TSU5HTEUoUE04NjBYX0FOQV9JTlBVVF9TRUxfMSwgMCwgNCwg
ZGFjX3RleHQpOworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgZGFjX2hz
MV9tdXggPQorCVNPQ19EQVBNX0VOVU0oIkRBQyBIUzEgTXV4IiwgZGFjX2hzMV9lbnVtKTsKKwor
LyogREFDIEhlYWRzZXQgMiBNdXggLyBNdXgxMSAqLworc3RhdGljIGNvbnN0IHN0cnVjdCBzb2Nf
ZW51bSBkYWNfaHMyX2VudW0gPQorCVNPQ19FTlVNX1NJTkdMRShQTTg2MFhfQU5BX0lOUFVUX1NF
TF8xLCAyLCA0LCBkYWNfdGV4dCk7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX2tjb250cm9s
X25ldyBkYWNfaHMyX211eCA9CisJU09DX0RBUE1fRU5VTSgiREFDIEhTMiBNdXgiLCBkYWNfaHMy
X2VudW0pOworCisvKiBEQUMgTGluZW91dCAxIE11eCAvIE11eDEyICovCitzdGF0aWMgY29uc3Qg
c3RydWN0IHNvY19lbnVtIGRhY19sbzFfZW51bSA9CisJU09DX0VOVU1fU0lOR0xFKFBNODYwWF9B
TkFfSU5QVVRfU0VMXzEsIDQsIDQsIGRhY190ZXh0KTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBz
bmRfa2NvbnRyb2xfbmV3IGRhY19sbzFfbXV4ID0KKwlTT0NfREFQTV9FTlVNKCJEQUMgTE8xIE11
eCIsIGRhY19sbzFfZW51bSk7CisKKy8qIERBQyBMaW5lb3V0IDIgTXV4IC8gTXV4MTMgKi8KK3N0
YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2VudW0gZGFjX2xvMl9lbnVtID0KKwlTT0NfRU5VTV9TSU5H
TEUoUE04NjBYX0FOQV9JTlBVVF9TRUxfMSwgNiwgNCwgZGFjX3RleHQpOworCitzdGF0aWMgY29u
c3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgZGFjX2xvMl9tdXggPQorCVNPQ19EQVBNX0VOVU0o
IkRBQyBMTzIgTXV4IiwgZGFjX2xvMl9lbnVtKTsKKworLyogREFDIFNwZWFya2VyIEVhcnBob25l
IE11eCAvIE11eDE0ICovCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIGRhY19zcGtfZWFy
X2VudW0gPQorCVNPQ19FTlVNX1NJTkdMRShQTTg2MFhfQU5BX0lOUFVUX1NFTF8yLCAwLCA0LCBk
YWNfdGV4dCk7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX2tjb250cm9sX25ldyBkYWNfc3Br
X2Vhcl9tdXggPQorCVNPQ19EQVBNX0VOVU0oIkRBQyBTUCBNdXgiLCBkYWNfc3BrX2Vhcl9lbnVt
KTsKKworLyogSGVhZHNldCAxIE11eCAvIE11eDE1ICovCitzdGF0aWMgY29uc3QgY2hhciAqaW5f
dGV4dFtdID0geworCSJEaWdpdGFsIiwgIkFuYWxvZyIsCit9OworCitzdGF0aWMgY29uc3Qgc3Ry
dWN0IHNvY19lbnVtIGhzMV9lbnVtID0KKwlTT0NfRU5VTV9TSU5HTEUoUE04NjBYX0FOQV9UT19B
TkEsIDAsIDIsIGluX3RleHQpOworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9u
ZXcgaHMxX211eCA9CisJU09DX0RBUE1fRU5VTSgiSGVhZHNldDEgTXV4IiwgaHMxX2VudW0pOwor
CisvKiBIZWFkc2V0IDIgTXV4IC8gTXV4MTYgKi8KK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc29jX2Vu
dW0gaHMyX2VudW0gPQorCVNPQ19FTlVNX1NJTkdMRShQTTg2MFhfQU5BX1RPX0FOQSwgMSwgMiwg
aW5fdGV4dCk7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX2tjb250cm9sX25ldyBoczJfbXV4
ID0KKwlTT0NfREFQTV9FTlVNKCJIZWFkc2V0MiBNdXgiLCBoczJfZW51bSk7CisKKy8qIExpbmVv
dXQgMSBNdXggLyBNdXgxNyAqLworc3RhdGljIGNvbnN0IHN0cnVjdCBzb2NfZW51bSBsbzFfZW51
bSA9CisJU09DX0VOVU1fU0lOR0xFKFBNODYwWF9BTkFfVE9fQU5BLCAyLCAyLCBpbl90ZXh0KTsK
Kworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IGxvMV9tdXggPQorCVNPQ19E
QVBNX0VOVU0oIkxpbmVvdXQxIE11eCIsIGxvMV9lbnVtKTsKKworLyogTGluZW91dCAyIE11eCAv
IE11eDE4ICovCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIGxvMl9lbnVtID0KKwlTT0Nf
RU5VTV9TSU5HTEUoUE04NjBYX0FOQV9UT19BTkEsIDMsIDIsIGluX3RleHQpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgbG8yX211eCA9CisJU09DX0RBUE1fRU5VTSgi
TGluZW91dDIgTXV4IiwgbG8yX2VudW0pOworCisvKiBTcGVha2VyIEVhcnBpZWNlIERlbXV4ICov
CitzdGF0aWMgY29uc3QgY2hhciAqc3BrX3RleHRbXSA9IHsKKwkiRWFycGllY2UiLCAiU3BlYWtl
ciIsCit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIHNwa19lbnVtID0KKwlTT0Nf
RU5VTV9TSU5HTEUoUE04NjBYX0FOQV9UT19BTkEsIDYsIDIsIHNwa190ZXh0KTsKKworc3RhdGlj
IGNvbnN0IHN0cnVjdCBzbmRfa2NvbnRyb2xfbmV3IHNwa19kZW11eCA9CisJU09DX0RBUE1fRU5V
TSgiU3BlYWtlciBFYXJwaWVjZSBEZW11eCIsIHNwa19lbnVtKTsKKworLyogTUlDIE11eCAvIE11
eDEgKi8KK3N0YXRpYyBjb25zdCBjaGFyICptaWNfdGV4dFtdID0geworCSJNaWMgMSIsICJNaWMg
MiIsCit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNvY19lbnVtIG1pY19lbnVtID0KKwlTT0Nf
RU5VTV9TSU5HTEUoUE04NjBYX0FEQ19BTkFfNCwgNCwgMiwgbWljX3RleHQpOworCitzdGF0aWMg
Y29uc3Qgc3RydWN0IHNuZF9rY29udHJvbF9uZXcgbWljX211eCA9CisJU09DX0RBUE1fRU5VTSgi
TUlDIE11eCIsIG1pY19lbnVtKTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfc29jX2RhcG1f
d2lkZ2V0IHBtODYweF9kYXBtX3dpZGdldHNbXSA9IHsKKwlTTkRfU09DX0RBUE1fQUlGX0lOKCJQ
Q00gU0RJIiwgIlBDTSBQbGF5YmFjayIsIDAsCisJCQkgICAgUE04NjBYX0FEQ19FTl8yLCAwLCAw
KSwKKwlTTkRfU09DX0RBUE1fQUlGX09VVCgiUENNIFNETyIsICJQQ00gQ2FwdHVyZSIsIDAsCisJ
CQkgICAgIFBNODYwWF9QQ01fSUZBQ0VfMywgMSwgMSksCisKKworCVNORF9TT0NfREFQTV9BSUZf
SU4oIkkyUyBESU4iLCAiSTJTIFBsYXliYWNrIiwgMCwKKwkJCSAgICBQTTg2MFhfREFDX0VOXzIs
IDAsIDApLAorCVNORF9TT0NfREFQTV9BSUZfSU4oIkkyUyBESU4xIiwgIkkyUyBQbGF5YmFjayIs
IDAsCisJCQkgICAgUE04NjBYX0RBQ19FTl8yLCAwLCAwKSwKKwlTTkRfU09DX0RBUE1fQUlGX09V
VCgiSTJTIERPVVQiLCAiSTJTIENhcHR1cmUiLCAwLAorCQkJICAgICBQTTg2MFhfSTJTX0lGQUNF
XzMsIDUsIDEpLAorCVNORF9TT0NfREFQTV9NVVgoIkkyUyBNaWMgTXV4IiwgU05EX1NPQ19OT1BN
LCAwLCAwLCAmaTJzX21pY19tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkFEQyBMZWZ0IE11eCIs
IFNORF9TT0NfTk9QTSwgMCwgMCwgJmFkY2xfbXV4KSwKKwlTTkRfU09DX0RBUE1fTVVYKCJBREMg
UmlnaHQgTXV4IiwgU05EX1NPQ19OT1BNLCAwLCAwLCAmYWRjcl9tdXgpLAorCVNORF9TT0NfREFQ
TV9NVVgoIkVDIE11eCIsIFNORF9TT0NfTk9QTSwgMCwgMCwgJmVjX211eCksCisJU05EX1NPQ19E
QVBNX01VWCgiQURDUiBFQyBNdXgiLCBTTkRfU09DX05PUE0sIDAsIDAsICZhZGNyX2VjX211eCks
CisJU05EX1NPQ19EQVBNX1NXSVRDSCgiTGVmdCBFUEEiLCBTTkRfU09DX05PUE0sIDAsIDAsCisJ
CQkgICAgJmxlcGFfc3dpdGNoX2NvbnRyb2xzKSwKKwlTTkRfU09DX0RBUE1fU1dJVENIKCJSaWdo
dCBFUEEiLCBTTkRfU09DX05PUE0sIDAsIDAsCisJCQkgICAgJnJlcGFfc3dpdGNoX2NvbnRyb2xz
KSwKKworCVNORF9TT0NfREFQTV9BRENfRSgiTGVmdCBBREMiLCBOVUxMLCBTTkRfU09DX05PUE0s
IDAsIDAsCisJCQkgICBwbTg2MHhfYWRjX2V2ZW50LAorCQkJICAgU05EX1NPQ19EQVBNX1BSRV9Q
TVUgfCBTTkRfU09DX0RBUE1fUFJFX1BNRCksCisJU05EX1NPQ19EQVBNX0FEQ19FKCJSaWdodCBB
REMiLCBOVUxMLCBTTkRfU09DX05PUE0sIDAsIDAsCisJCQkgICBwbTg2MHhfYWRjX2V2ZW50LAor
CQkJICAgU05EX1NPQ19EQVBNX1BSRV9QTVUgfCBTTkRfU09DX0RBUE1fUFJFX1BNRCksCisKKwlT
TkRfU09DX0RBUE1fU1dJVENIKCJBVVgxIFN3aXRjaCIsIFNORF9TT0NfTk9QTSwgMCwgMCwKKwkJ
CSAgICAmYXV4MV9zd2l0Y2hfY29udHJvbHMpLAorCVNORF9TT0NfREFQTV9TV0lUQ0goIkFVWDIg
U3dpdGNoIiwgU05EX1NPQ19OT1BNLCAwLCAwLAorCQkJICAgICZhdXgyX3N3aXRjaF9jb250cm9s
cyksCisKKwlTTkRfU09DX0RBUE1fTVVYKCJNSUMgTXV4IiwgU05EX1NPQ19OT1BNLCAwLCAwLCAm
bWljX211eCksCisJU05EX1NPQ19EQVBNX01JQ0JJQVNfRSgiTWljMSBCaWFzIiwgU05EX1NPQ19O
T1BNLCAwLCAwLAorCQkJICAgICAgICZwbTg2MHhfbWljMV9ldmVudCwKKwkJCSAgICAgICBTTkRf
U09DX0RBUE1fUE9TVF9QTVUgfCBTTkRfU09DX0RBUE1fUFJFX1BNRCksCisJU05EX1NPQ19EQVBN
X01JQ0JJQVMoIk1pYzMgQmlhcyIsIFBNODYwWF9BRENfQU5BXzEsIDcsIDApLAorCVNORF9TT0Nf
REFQTV9QR0EoIk1JQzEgVm9sdW1lIiwgUE04NjBYX0FEQ19FTl8xLCAyLCAwLCBOVUxMLCAwKSwK
KwlTTkRfU09DX0RBUE1fUEdBKCJNSUMzIFZvbHVtZSIsIFBNODYwWF9BRENfRU5fMSwgMywgMCwg
TlVMTCwgMCksCisJU05EX1NPQ19EQVBNX1BHQSgiQVVYMSBWb2x1bWUiLCBQTTg2MFhfQURDX0VO
XzEsIDQsIDAsIE5VTEwsIDApLAorCVNORF9TT0NfREFQTV9QR0EoIkFVWDIgVm9sdW1lIiwgUE04
NjBYX0FEQ19FTl8xLCA1LCAwLCBOVUxMLCAwKSwKKwlTTkRfU09DX0RBUE1fUEdBKCJTaWRldG9u
ZSBQR0EiLCBQTTg2MFhfQURDX0VOXzIsIDEsIDAsIE5VTEwsIDApLAorCVNORF9TT0NfREFQTV9Q
R0EoIkxvZmkgUEdBIiwgUE04NjBYX0FEQ19FTl8yLCAyLCAwLCBOVUxMLCAwKSwKKworCVNORF9T
T0NfREFQTV9JTlBVVCgiQVVYMSIpLAorCVNORF9TT0NfREFQTV9JTlBVVCgiQVVYMiIpLAorCVNO
RF9TT0NfREFQTV9JTlBVVCgiTUlDMVAiKSwKKwlTTkRfU09DX0RBUE1fSU5QVVQoIk1JQzFOIiks
CisJU05EX1NPQ19EQVBNX0lOUFVUKCJNSUMyUCIpLAorCVNORF9TT0NfREFQTV9JTlBVVCgiTUlD
Mk4iKSwKKwlTTkRfU09DX0RBUE1fSU5QVVQoIk1JQzNQIiksCisJU05EX1NPQ19EQVBNX0lOUFVU
KCJNSUMzTiIpLAorCisJU05EX1NPQ19EQVBNX0RBQ19FKCJMZWZ0IERBQyIsIE5VTEwsIFNORF9T
T0NfTk9QTSwgMCwgMCwKKwkJCSAgIHBtODYweF9kYWNfZXZlbnQsCisJCQkgICBTTkRfU09DX0RB
UE1fUFJFX1BNVSB8IFNORF9TT0NfREFQTV9QUkVfUE1EKSwKKwlTTkRfU09DX0RBUE1fREFDX0Uo
IlJpZ2h0IERBQyIsIE5VTEwsIFNORF9TT0NfTk9QTSwgMCwgMCwKKwkJCSAgIHBtODYweF9kYWNf
ZXZlbnQsCisJCQkgICBTTkRfU09DX0RBUE1fUFJFX1BNVSB8IFNORF9TT0NfREFQTV9QUkVfUE1E
KSwKKworCVNORF9TT0NfREFQTV9NVVgoIkkyUyBESU4gTXV4IiwgU05EX1NPQ19OT1BNLCAwLCAw
LCAmaTJzX2Rpbl9tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkRBQyBIUzEgTXV4IiwgU05EX1NP
Q19OT1BNLCAwLCAwLCAmZGFjX2hzMV9tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkRBQyBIUzIg
TXV4IiwgU05EX1NPQ19OT1BNLCAwLCAwLCAmZGFjX2hzMl9tdXgpLAorCVNORF9TT0NfREFQTV9N
VVgoIkRBQyBMTzEgTXV4IiwgU05EX1NPQ19OT1BNLCAwLCAwLCAmZGFjX2xvMV9tdXgpLAorCVNO
RF9TT0NfREFQTV9NVVgoIkRBQyBMTzIgTXV4IiwgU05EX1NPQ19OT1BNLCAwLCAwLCAmZGFjX2xv
Ml9tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkRBQyBTUCBNdXgiLCBTTkRfU09DX05PUE0sIDAs
IDAsICZkYWNfc3BrX2Vhcl9tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkhlYWRzZXQxIE11eCIs
IFNORF9TT0NfTk9QTSwgMCwgMCwgJmhzMV9tdXgpLAorCVNORF9TT0NfREFQTV9NVVgoIkhlYWRz
ZXQyIE11eCIsIFNORF9TT0NfTk9QTSwgMCwgMCwgJmhzMl9tdXgpLAorCVNORF9TT0NfREFQTV9N
VVgoIkxpbmVvdXQxIE11eCIsIFNORF9TT0NfTk9QTSwgMCwgMCwgJmxvMV9tdXgpLAorCVNORF9T
T0NfREFQTV9NVVgoIkxpbmVvdXQyIE11eCIsIFNORF9TT0NfTk9QTSwgMCwgMCwgJmxvMl9tdXgp
LAorCVNORF9TT0NfREFQTV9NVVgoIlNwZWFrZXIgRWFycGllY2UgRGVtdXgiLCBTTkRfU09DX05P
UE0sIDAsIDAsCisJCQkgJnNwa19kZW11eCksCisKKworCVNORF9TT0NfREFQTV9QR0EoIkhlYWRz
ZXQxIFBHQSIsIFBNODYwWF9EQUNfRU5fMSwgMCwgMCwgTlVMTCwgMCksCisJU05EX1NPQ19EQVBN
X1BHQSgiSGVhZHNldDIgUEdBIiwgUE04NjBYX0RBQ19FTl8xLCAxLCAwLCBOVUxMLCAwKSwKKwlT
TkRfU09DX0RBUE1fT1VUUFVUKCJIUzEiKSwKKwlTTkRfU09DX0RBUE1fT1VUUFVUKCJIUzIiKSwK
KwlTTkRfU09DX0RBUE1fUEdBKCJMaW5lb3V0MSBQR0EiLCBQTTg2MFhfREFDX0VOXzEsIDIsIDAs
IE5VTEwsIDApLAorCVNORF9TT0NfREFQTV9QR0EoIkxpbmVvdXQyIFBHQSIsIFBNODYwWF9EQUNf
RU5fMSwgMywgMCwgTlVMTCwgMCksCisJU05EX1NPQ19EQVBNX09VVFBVVCgiTElORU9VVDEiKSwK
KwlTTkRfU09DX0RBUE1fT1VUUFVUKCJMSU5FT1VUMiIpLAorCVNORF9TT0NfREFQTV9QR0EoIkVh
cnBpZWNlIFBHQSIsIFBNODYwWF9EQUNfRU5fMSwgNCwgMCwgTlVMTCwgMCksCisJU05EX1NPQ19E
QVBNX09VVFBVVCgiRUFSUCIpLAorCVNORF9TT0NfREFQTV9PVVRQVVQoIkVBUk4iKSwKKwlTTkRf
U09DX0RBUE1fUEdBKCJTcGVha2VyIFBHQSIsIFBNODYwWF9EQUNfRU5fMSwgNSwgMCwgTlVMTCwg
MCksCisJU05EX1NPQ19EQVBNX09VVFBVVCgiTFNQIiksCisJU05EX1NPQ19EQVBNX09VVFBVVCgi
TFNOIiksCisJU05EX1NPQ19EQVBNX1JFRyhzbmRfc29jX2RhcG1fc3VwcGx5LCAiVkNPREVDIiwg
UE04NjBYX0FVRElPX1NVUFBMSUVTXzIsCisJCQkgMCwgU1VQUExZX01BU0ssIFNVUFBMWV9NQVNL
LCAwKSwKKworCVNORF9TT0NfREFQTV9QT1NUKCJSU1lOQyIsIHBtODYweF9yc3luY19ldmVudCks
Cit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNuZF9zb2NfZGFwbV9yb3V0ZSBhdWRpb19tYXBb
XSA9IHsKKwkvKiBzdXBwbHkgKi8KKwl7IkxlZnQgREFDIiwgTlVMTCwgIlZDT0RFQyJ9LAorCXsi
UmlnaHQgREFDIiwgTlVMTCwgIlZDT0RFQyJ9LAorCXsiTGVmdCBBREMiLCBOVUxMLCAiVkNPREVD
In0sCisJeyJSaWdodCBBREMiLCBOVUxMLCAiVkNPREVDIn0sCisKKwkvKiBQQ00vQUlGMSBJbnB1
dHMgKi8KKwl7IlBDTSBTRE8iLCBOVUxMLCAiQURDIExlZnQgTXV4In0sCisJeyJQQ00gU0RPIiwg
TlVMTCwgIkFEQ1IgRUMgTXV4In0sCisKKwkvKiBQQ00vQUZJMiBPdXRwdXRzICovCisJeyJMb2Zp
IFBHQSIsIE5VTEwsICJQQ00gU0RJIn0sCisJeyJMb2ZpIFBHQSIsIE5VTEwsICJTaWRldG9uZSBQ
R0EifSwKKwl7IkxlZnQgREFDIiwgTlVMTCwgIkxvZmkgUEdBIn0sCisJeyJSaWdodCBEQUMiLCBO
VUxMLCAiTG9maSBQR0EifSwKKworCS8qIEkyUy9BSUYyIElucHV0cyAqLworCXsiTUlDIE11eCIs
ICJNaWMgMSIsICJNSUMxUCJ9LAorCXsiTUlDIE11eCIsICJNaWMgMSIsICJNSUMxTiJ9LAorCXsi
TUlDIE11eCIsICJNaWMgMiIsICJNSUMyUCJ9LAorCXsiTUlDIE11eCIsICJNaWMgMiIsICJNSUMy
TiJ9LAorCXsiTUlDMSBWb2x1bWUiLCBOVUxMLCAiTUlDIE11eCJ9LAorCXsiTUlDMyBWb2x1bWUi
LCBOVUxMLCAiTUlDM1AifSwKKwl7Ik1JQzMgVm9sdW1lIiwgTlVMTCwgIk1JQzNOIn0sCisJeyJM
ZWZ0IEFEQyIsIE5VTEwsICJNSUMxIFZvbHVtZSJ9LAorCXsiUmlnaHQgQURDIiwgTlVMTCwgIk1J
QzMgVm9sdW1lIn0sCisJeyJBREMgTGVmdCBNdXgiLCAiQURDUiIsICJSaWdodCBBREMifSwKKwl7
IkFEQyBMZWZ0IE11eCIsICJBRENMIiwgIkxlZnQgQURDIn0sCisJeyJBREMgUmlnaHQgTXV4Iiwg
IkFEQ0wiLCAiTGVmdCBBREMifSwKKwl7IkFEQyBSaWdodCBNdXgiLCAiQURDUiIsICJSaWdodCBB
REMifSwKKwl7IkxlZnQgRVBBIiwgIlN3aXRjaCIsICJMZWZ0IERBQyJ9LAorCXsiUmlnaHQgRVBB
IiwgIlN3aXRjaCIsICJSaWdodCBEQUMifSwKKwl7IkVDIE11eCIsICJMZWZ0IiwgIkxlZnQgREFD
In0sCisJeyJFQyBNdXgiLCAiUmlnaHQiLCAiUmlnaHQgREFDIn0sCisJeyJFQyBNdXgiLCAiTGVm
dCArIFJpZ2h0IiwgIkxlZnQgREFDIn0sCisJeyJFQyBNdXgiLCAiTGVmdCArIFJpZ2h0IiwgIlJp
Z2h0IERBQyJ9LAorCXsiQURDUiBFQyBNdXgiLCAiQURDUiIsICJBREMgUmlnaHQgTXV4In0sCisJ
eyJBRENSIEVDIE11eCIsICJFQyIsICJFQyBNdXgifSwKKwl7IkkyUyBNaWMgTXV4IiwgIkV4IFBB
IiwgIkxlZnQgRVBBIn0sCisJeyJJMlMgTWljIE11eCIsICJFeCBQQSIsICJSaWdodCBFUEEifSwK
Kwl7IkkyUyBNaWMgTXV4IiwgIkFEQyIsICJBREMgTGVmdCBNdXgifSwKKwl7IkkyUyBNaWMgTXV4
IiwgIkFEQyIsICJBRENSIEVDIE11eCJ9LAorCXsiSTJTIERPVVQiLCBOVUxMLCAiSTJTIE1pYyBN
dXgifSwKKworCS8qIEkyUy9BSUYyIE91dHB1dHMgKi8KKwl7IkkyUyBESU4gTXV4IiwgIkRJTiIs
ICJJMlMgRElOIn0sCisJeyJJMlMgRElOIE11eCIsICJESU4xIiwgIkkyUyBESU4xIn0sCisJeyJM
ZWZ0IERBQyIsIE5VTEwsICJJMlMgRElOIE11eCJ9LAorCXsiUmlnaHQgREFDIiwgTlVMTCwgIkky
UyBESU4gTXV4In0sCisJeyJEQUMgSFMxIE11eCIsICJMZWZ0IiwgIkxlZnQgREFDIn0sCisJeyJE
QUMgSFMxIE11eCIsICJSaWdodCIsICJSaWdodCBEQUMifSwKKwl7IkRBQyBIUzIgTXV4IiwgIkxl
ZnQiLCAiTGVmdCBEQUMifSwKKwl7IkRBQyBIUzIgTXV4IiwgIlJpZ2h0IiwgIlJpZ2h0IERBQyJ9
LAorCXsiREFDIExPMSBNdXgiLCAiTGVmdCIsICJMZWZ0IERBQyJ9LAorCXsiREFDIExPMSBNdXgi
LCAiUmlnaHQiLCAiUmlnaHQgREFDIn0sCisJeyJEQUMgTE8yIE11eCIsICJMZWZ0IiwgIkxlZnQg
REFDIn0sCisJeyJEQUMgTE8yIE11eCIsICJSaWdodCIsICJSaWdodCBEQUMifSwKKwl7IkhlYWRz
ZXQxIE11eCIsICJEaWdpdGFsIiwgIkRBQyBIUzEgTXV4In0sCisJeyJIZWFkc2V0MiBNdXgiLCAi
RGlnaXRhbCIsICJEQUMgSFMyIE11eCJ9LAorCXsiTGluZW91dDEgTXV4IiwgIkRpZ2l0YWwiLCAi
REFDIExPMSBNdXgifSwKKwl7IkxpbmVvdXQyIE11eCIsICJEaWdpdGFsIiwgIkRBQyBMTzIgTXV4
In0sCisJeyJIZWFkc2V0MSBQR0EiLCBOVUxMLCAiSGVhZHNldDEgTXV4In0sCisJeyJIZWFkc2V0
MiBQR0EiLCBOVUxMLCAiSGVhZHNldDIgTXV4In0sCisJeyJMaW5lb3V0MSBQR0EiLCBOVUxMLCAi
TGluZW91dDEgTXV4In0sCisJeyJMaW5lb3V0MiBQR0EiLCBOVUxMLCAiTGluZW91dDIgTXV4In0s
CisJeyJEQUMgU1AgTXV4IiwgIkxlZnQiLCAiTGVmdCBEQUMifSwKKwl7IkRBQyBTUCBNdXgiLCAi
UmlnaHQiLCAiUmlnaHQgREFDIn0sCisJeyJTcGVha2VyIEVhcnBpZWNlIERlbXV4IiwgIlNwZWFr
ZXIiLCAiREFDIFNQIE11eCJ9LAorCXsiU3BlYWtlciBQR0EiLCBOVUxMLCAiU3BlYWtlciBFYXJw
aWVjZSBEZW11eCJ9LAorCXsiRWFycGllY2UgUEdBIiwgTlVMTCwgIlNwZWFrZXIgRWFycGllY2Ug
RGVtdXgifSwKKworCXsiSFMxIiwgTlVMTCwgIkhlYWRzZXQxIFBHQSJ9LAorCXsiSFMyIiwgTlVM
TCwgIkhlYWRzZXQyIFBHQSJ9LAorCXsiTElORU9VVDEiLCBOVUxMLCAiTGluZW91dDEgUEdBIn0s
CisJeyJMSU5FT1VUMiIsIE5VTEwsICJMaW5lb3V0MiBQR0EifSwKKwl7IkxTUCIsIE5VTEwsICJT
cGVha2VyIFBHQSJ9LAorCXsiTFNOIiwgTlVMTCwgIlNwZWFrZXIgUEdBIn0sCisJeyJFQVJQIiwg
TlVMTCwgIkVhcnBpZWNlIFBHQSJ9LAorCXsiRUFSTiIsIE5VTEwsICJFYXJwaWVjZSBQR0EifSwK
K307CisKK3N0YXRpYyBpbnQgcG04NjB4X2RpZ2l0YWxfbXV0ZShzdHJ1Y3Qgc25kX3NvY19kYWkg
KmNvZGVjX2RhaSwgaW50IG11dGUpCit7CisJc3RydWN0IHNuZF9zb2NfY29kZWMgKmNvZGVjID0g
Y29kZWNfZGFpLT5jb2RlYzsKKwlpbnQgZGF0YSA9IDA7CisKKwlpZiAobXV0ZSkKKwkJZGF0YSA9
IERBQ19NVVRFOworCXNuZF9zb2NfdXBkYXRlX2JpdHMoY29kZWMsIFBNODYwWF9EQUNfT0ZGU0VU
LCBEQUNfTVVURSwgZGF0YSk7CisJc25kX3NvY191cGRhdGVfYml0cyhjb2RlYywgUE04NjBYX0VB
Ul9DVFJMXzIsCisJCQkgICAgUlNZTkNfQ0hBTkdFLCBSU1lOQ19DSEFOR0UpOworCXJldHVybiAw
OworfQorCitzdGF0aWMgaW50IHNldF9kYWlfZm10KHN0cnVjdCBwbTg2MHhfcHJpdiAqcG04NjB4
LCB1bnNpZ25lZCBpbnQgZm10LAorCQkgICAgICAgdW5zaWduZWQgY2hhciAqaW5mLCB1bnNpZ25l
ZCBjaGFyICptYXNrKQoreworCSptYXNrIHw9IFBDTV9JTkYyX0JDTEsgfCBQQ01fSU5GMl9GUyB8
IFBDTV9JTkYyX01BU1RFUjsKKworCS8qIHNldCBtYXN0ZXIvc2xhdmUgYXVkaW8gaW50ZXJmYWNl
ICovCisJc3dpdGNoIChmbXQgJiBTTkRfU09DX0RBSUZNVF9NQVNURVJfTUFTSykgeworCWNhc2Ug
U05EX1NPQ19EQUlGTVRfQ0JNX0NGTToKKwljYXNlIFNORF9TT0NfREFJRk1UX0NCTV9DRlM6CisJ
CWlmIChwbTg2MHgtPmRpciA9PSBQTTg2MFhfQ0xLX0RJUl9PVVQpCisJCQkqaW5mIHw9IFBDTV9J
TkYyX01BU1RFUjsKKwkJZWxzZQorCQkJcmV0dXJuIC1FSU5WQUw7CisJCWJyZWFrOworCWNhc2Ug
U05EX1NPQ19EQUlGTVRfQ0JTX0NGUzoKKwkJaWYgKHBtODYweC0+ZGlyID09IFBNODYwWF9DTEtf
RElSX0lOKQorCQkJKmluZiAmPSB+UENNX0lORjJfTUFTVEVSOworCQllbHNlCisJCQlyZXR1cm4g
LUVJTlZBTDsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ
c3dpdGNoIChmbXQgJiBTTkRfU09DX0RBSUZNVF9GT1JNQVRfTUFTSykgeworCWNhc2UgU05EX1NP
Q19EQUlGTVRfSTJTOgorCQkqaW5mIHw9IFBDTV9FWEFDVF9JMlM7CisJCWJyZWFrOworCWRlZmF1
bHQ6CisJCXJldHVybiAtRUlOVkFMOworCX0KKwkqbWFzayB8PSBQQ01fTU9ERV9NQVNLOworCXJl
dHVybiAwOworfQorCitzdGF0aWMgaW50IHBtODYweF9wY21faHdfcGFyYW1zKHN0cnVjdCBzbmRf
cGNtX3N1YnN0cmVhbSAqc3Vic3RyZWFtLAorCQkJCXN0cnVjdCBzbmRfcGNtX2h3X3BhcmFtcyAq
cGFyYW1zLAorCQkJCXN0cnVjdCBzbmRfc29jX2RhaSAqZGFpKQoreworCXN0cnVjdCBzbmRfc29j
X2NvZGVjICpjb2RlYyA9IGRhaS0+Y29kZWM7CisJdW5zaWduZWQgY2hhciBpbmYgPSAwLCBtYXNr
ID0gMDsKKworCS8qIGJpdCBzaXplICovCisJc3dpdGNoIChwYXJhbXNfZm9ybWF0KHBhcmFtcykp
IHsKKwljYXNlIFNORFJWX1BDTV9GT1JNQVRfUzE2X0xFOgorCQlpbmYgJj0gflBDTV9JTkYyXzE4
V0w7CisJCWJyZWFrOworCWNhc2UgU05EUlZfUENNX0ZPUk1BVF9TMThfM0xFOgorCQlpbmYgfD0g
UENNX0lORjJfMThXTDsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJ
fQorCW1hc2sgfD0gUENNX0lORjJfMThXTDsKKwlzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVjLCBQ
TTg2MFhfUENNX0lGQUNFXzIsIG1hc2ssIGluZik7CisKKwkvKiBzYW1wbGUgcmF0ZSAqLworCXN3
aXRjaCAocGFyYW1zX3JhdGUocGFyYW1zKSkgeworCWNhc2UgODAwMDoKKwkJaW5mID0gMDsKKwkJ
YnJlYWs7CisJY2FzZSAxNjAwMDoKKwkJaW5mID0gMzsKKwkJYnJlYWs7CisJY2FzZSAzMjAwMDoK
KwkJaW5mID0gNjsKKwkJYnJlYWs7CisJY2FzZSA0ODAwMDoKKwkJaW5mID0gODsKKwkJYnJlYWs7
CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCXNuZF9zb2NfdXBkYXRlX2JpdHMo
Y29kZWMsIFBNODYwWF9QQ01fUkFURSwgMHgwZiwgaW5mKTsKKworCXJldHVybiAwOworfQorCitz
dGF0aWMgaW50IHBtODYweF9wY21fc2V0X2RhaV9mbXQoc3RydWN0IHNuZF9zb2NfZGFpICpjb2Rl
Y19kYWksCisJCQkJICB1bnNpZ25lZCBpbnQgZm10KQoreworCXN0cnVjdCBzbmRfc29jX2NvZGVj
ICpjb2RlYyA9IGNvZGVjX2RhaS0+Y29kZWM7CisJc3RydWN0IHBtODYweF9wcml2ICpwbTg2MHgg
PSBzbmRfc29jX2NvZGVjX2dldF9kcnZkYXRhKGNvZGVjKTsKKwl1bnNpZ25lZCBjaGFyIGluZiA9
IDAsIG1hc2sgPSAwOworCWludCByZXQ7CisKKwlyZXQgPSBzZXRfZGFpX2ZtdChwbTg2MHgsIGZt
dCwgJmluZiwgJm1hc2spOworCWlmICghcmV0KQorCQlzbmRfc29jX3VwZGF0ZV9iaXRzKGNvZGVj
LCBQTTg2MFhfUENNX0lGQUNFXzIsIG1hc2ssIGluZik7CisJcmV0dXJuIHJldDsKK30KKworc3Rh
dGljIGludCBwbTg2MHhfc2V0X2RhaV9zeXNjbGsoc3RydWN0IHNuZF9zb2NfZGFpICpjb2RlY19k
YWksCisJCQkJIGludCBjbGtfaWQsIHVuc2lnbmVkIGludCBmcmVxLCBpbnQgZGlyKQoreworCXN0
cnVjdCBzbmRfc29jX2NvZGVjICpjb2RlYyA9IGNvZGVjX2RhaS0+Y29kZWM7CisJc3RydWN0IHBt
ODYweF9wcml2ICpwbTg2MHggPSBzbmRfc29jX2NvZGVjX2dldF9kcnZkYXRhKGNvZGVjKTsKKwor
CWlmIChkaXIgPT0gUE04NjBYX0NMS19ESVJfT1VUKQorCQlwbTg2MHgtPmRpciA9IFBNODYwWF9D
TEtfRElSX09VVDsKKwllbHNlCisJCXBtODYweC0+ZGlyID0gUE04NjBYX0NMS19ESVJfSU47CisK
KwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBwbTg2MHhfaTJzX2h3X3BhcmFtcyhzdHJ1Y3Qg
c25kX3BjbV9zdWJzdHJlYW0gKnN1YnN0cmVhbSwKKwkJCQlzdHJ1Y3Qgc25kX3BjbV9od19wYXJh
bXMgKnBhcmFtcywKKwkJCQlzdHJ1Y3Qgc25kX3NvY19kYWkgKmRhaSkKK3sKKwlzdHJ1Y3Qgc25k
X3NvY19jb2RlYyAqY29kZWMgPSBkYWktPmNvZGVjOworCXVuc2lnbmVkIGNoYXIgaW5mOworCisJ
LyogYml0IHNpemUgKi8KKwlzd2l0Y2ggKHBhcmFtc19mb3JtYXQocGFyYW1zKSkgeworCWNhc2Ug
U05EUlZfUENNX0ZPUk1BVF9TMTZfTEU6CisJCWluZiA9IDA7CisJCWJyZWFrOworCWNhc2UgU05E
UlZfUENNX0ZPUk1BVF9TMThfM0xFOgorCQlpbmYgPSBQQ01fSU5GMl8xOFdMOworCQlicmVhazsK
KwlkZWZhdWx0OgorCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisJc25kX3NvY191cGRhdGVfYml0cyhj
b2RlYywgUE04NjBYX0kyU19JRkFDRV8yLCBQQ01fSU5GMl8xOFdMLCBpbmYpOworCisJLyogc2Ft
cGxlIHJhdGUgKi8KKwlzd2l0Y2ggKHBhcmFtc19yYXRlKHBhcmFtcykpIHsKKwljYXNlIDgwMDA6
CisJCWluZiA9IDA7CisJCWJyZWFrOworCWNhc2UgMTEwMjU6CisJCWluZiA9IDE7CisJCWJyZWFr
OworCWNhc2UgMTYwMDA6CisJCWluZiA9IDM7CisJCWJyZWFrOworCWNhc2UgMjIwNTA6CisJCWlu
ZiA9IDQ7CisJCWJyZWFrOworCWNhc2UgMzIwMDA6CisJCWluZiA9IDY7CisJCWJyZWFrOworCWNh
c2UgNDQxMDA6CisJCWluZiA9IDc7CisJCWJyZWFrOworCWNhc2UgNDgwMDA6CisJCWluZiA9IDg7
CisJCWJyZWFrOworCWRlZmF1bHQ6CisJCXJldHVybiAtRUlOVkFMOworCX0KKwlzbmRfc29jX3Vw
ZGF0ZV9iaXRzKGNvZGVjLCBQTTg2MFhfSTJTX0lGQUNFXzQsIDB4ZiwgaW5mKTsKKworCXJldHVy
biAwOworfQorCitzdGF0aWMgaW50IHBtODYweF9pMnNfc2V0X2RhaV9mbXQoc3RydWN0IHNuZF9z
b2NfZGFpICpjb2RlY19kYWksCisJCQkJICB1bnNpZ25lZCBpbnQgZm10KQoreworCXN0cnVjdCBz
bmRfc29jX2NvZGVjICpjb2RlYyA9IGNvZGVjX2RhaS0+Y29kZWM7CisJc3RydWN0IHBtODYweF9w
cml2ICpwbTg2MHggPSBzbmRfc29jX2NvZGVjX2dldF9kcnZkYXRhKGNvZGVjKTsKKwl1bnNpZ25l
ZCBjaGFyIGluZiA9IDAsIG1hc2sgPSAwOworCWludCByZXQ7CisKKwlyZXQgPSBzZXRfZGFpX2Zt
dChwbTg2MHgsIGZtdCwgJmluZiwgJm1hc2spOworCWlmICghcmV0KQorCQlzbmRfc29jX3VwZGF0
ZV9iaXRzKGNvZGVjLCBQTTg2MFhfSTJTX0lGQUNFXzIsIG1hc2ssIGluZik7CisJcmV0dXJuIHJl
dDsKK30KKworc3RhdGljIGludCBwbTg2MHhfc2V0X2JpYXNfbGV2ZWwoc3RydWN0IHNuZF9zb2Nf
Y29kZWMgKmNvZGVjLAorCQkJCSBlbnVtIHNuZF9zb2NfYmlhc19sZXZlbCBsZXZlbCkKK3sKKwlp
bnQgZGF0YTsKKworCXN3aXRjaCAobGV2ZWwpIHsKKwljYXNlIFNORF9TT0NfQklBU19PTjoKKwkJ
YnJlYWs7CisKKwljYXNlIFNORF9TT0NfQklBU19QUkVQQVJFOgorCQlicmVhazsKKworCWNhc2Ug
U05EX1NPQ19CSUFTX1NUQU5EQlk6CisJCWlmIChjb2RlYy0+Ymlhc19sZXZlbCA9PSBTTkRfU09D
X0JJQVNfT0ZGKSB7CisJCQkvKiBFbmFibGUgQXVkaW8gUExMICYgQXVkaW8gc2VjdGlvbiAqLwor
CQkJZGF0YSA9IEFVRElPX1BMTCB8IEFVRElPX1NFQ1RJT05fUkVTRVQKKwkJCQl8IEFVRElPX1NF
Q1RJT05fT047CisJCQlwbTg2MHhfcmVnX3dyaXRlKGNvZGVjLT5jb250cm9sX2RhdGEsIFJFR19N
SVNDMiwgZGF0YSk7CisJCX0KKwkJYnJlYWs7CisKKwljYXNlIFNORF9TT0NfQklBU19PRkY6CisJ
CWRhdGEgPSBBVURJT19QTEwgfCBBVURJT19TRUNUSU9OX1JFU0VUIHwgQVVESU9fU0VDVElPTl9P
TjsKKwkJcG04NjB4X3NldF9iaXRzKGNvZGVjLT5jb250cm9sX2RhdGEsIFJFR19NSVNDMiwgZGF0
YSwgMCk7CisJCWJyZWFrOworCX0KKwljb2RlYy0+Ymlhc19sZXZlbCA9IGxldmVsOworCXJldHVy
biAwOworfQorCitzdGF0aWMgc3RydWN0IHNuZF9zb2NfZGFpX29wcyBwbTg2MHhfcGNtX2RhaV9v
cHMgPSB7CisJLmRpZ2l0YWxfbXV0ZQk9IHBtODYweF9kaWdpdGFsX211dGUsCisJLmh3X3BhcmFt
cwk9IHBtODYweF9wY21faHdfcGFyYW1zLAorCS5zZXRfZm10CT0gcG04NjB4X3BjbV9zZXRfZGFp
X2ZtdCwKKwkuc2V0X3N5c2Nsawk9IHBtODYweF9zZXRfZGFpX3N5c2NsaywKK307CisKK3N0YXRp
YyBzdHJ1Y3Qgc25kX3NvY19kYWlfb3BzIHBtODYweF9pMnNfZGFpX29wcyA9IHsKKwkuZGlnaXRh
bF9tdXRlCT0gcG04NjB4X2RpZ2l0YWxfbXV0ZSwKKwkuaHdfcGFyYW1zCT0gcG04NjB4X2kyc19o
d19wYXJhbXMsCisJLnNldF9mbXQJPSBwbTg2MHhfaTJzX3NldF9kYWlfZm10LAorCS5zZXRfc3lz
Y2xrCT0gcG04NjB4X3NldF9kYWlfc3lzY2xrLAorfTsKKworI2RlZmluZSBQTTg2MFhfUkFURVMJ
KFNORFJWX1BDTV9SQVRFXzgwMDAgfCBTTkRSVl9QQ01fUkFURV8xNjAwMCB8CVwKKwkJCSBTTkRS
Vl9QQ01fUkFURV8zMjAwMCB8IFNORFJWX1BDTV9SQVRFXzQ4MDAwKQorCitzdGF0aWMgc3RydWN0
IHNuZF9zb2NfZGFpX2RyaXZlciBwbTg2MHhfZGFpW10gPSB7CisJeworCQkvKiBEQUkgUENNICov
CisJCS5uYW1lCT0gIjg4cG04NjB4LXBjbSIsCisJCS5pZAk9IDEsCisJCS5wbGF5YmFjayA9IHsK
KwkJCS5zdHJlYW1fbmFtZQk9ICJQQ00gUGxheWJhY2siLAorCQkJLmNoYW5uZWxzX21pbgk9IDIs
CisJCQkuY2hhbm5lbHNfbWF4CT0gMiwKKwkJCS5yYXRlcwkJPSBQTTg2MFhfUkFURVMsCisJCQku
Zm9ybWF0cwk9IFNORFJWX1BDTV9GT1JNQVRfUzE2X0xFIHwgXAorCQkJCQkgIFNORFJWX1BDTV9G
T1JNQVRfUzE4XzNMRSwKKwkJfSwKKwkJLmNhcHR1cmUgPSB7CisJCQkuc3RyZWFtX25hbWUJPSAi
UENNIENhcHR1cmUiLAorCQkJLmNoYW5uZWxzX21pbgk9IDIsCisJCQkuY2hhbm5lbHNfbWF4CT0g
MiwKKwkJCS5yYXRlcwkJPSBQTTg2MFhfUkFURVMsCisJCQkuZm9ybWF0cwk9IFNORFJWX1BDTV9G
T1JNQVRfUzE2X0xFIHwgXAorCQkJCQkgIFNORFJWX1BDTV9GT1JNQVRfUzE4XzNMRSwKKwkJfSwK
KwkJLm9wcwk9ICZwbTg2MHhfcGNtX2RhaV9vcHMsCisJfSwgeworCQkvKiBEQUkgSTJTICovCisJ
CS5uYW1lCT0gIjg4cG04NjB4LWkycyIsCisJCS5pZAk9IDIsCisJCS5wbGF5YmFjayA9IHsKKwkJ
CS5zdHJlYW1fbmFtZQk9ICJJMlMgUGxheWJhY2siLAorCQkJLmNoYW5uZWxzX21pbgk9IDIsCisJ
CQkuY2hhbm5lbHNfbWF4CT0gMiwKKwkJCS5yYXRlcwkJPSBTTkRSVl9QQ01fUkFURV84MDAwXzQ4
MDAwLAorCQkJLmZvcm1hdHMJPSBTTkRSVl9QQ01fRk9STUFUX1MxNl9MRSB8IFwKKwkJCQkJICBT
TkRSVl9QQ01fRk9STUFUX1MxOF8zTEUsCisJCX0sCisJCS5jYXB0dXJlID0geworCQkJLnN0cmVh
bV9uYW1lCT0gIkkyUyBDYXB0dXJlIiwKKwkJCS5jaGFubmVsc19taW4JPSAyLAorCQkJLmNoYW5u
ZWxzX21heAk9IDIsCisJCQkucmF0ZXMJCT0gU05EUlZfUENNX1JBVEVfODAwMF80ODAwMCwKKwkJ
CS5mb3JtYXRzCT0gU05EUlZfUENNX0ZPUk1BVF9TMTZfTEUgfCBcCisJCQkJCSAgU05EUlZfUENN
X0ZPUk1BVF9TMThfM0xFLAorCQl9LAorCQkub3BzCT0gJnBtODYweF9pMnNfZGFpX29wcywKKwl9
LAorfTsKKworc3RhdGljIGlycXJldHVybl90IHBtODYweF9jb2RlY19oYW5kbGVyKGludCBpcnEs
IHZvaWQgKmRhdGEpCit7CisJc3RydWN0IHBtODYweF9wcml2ICpwbTg2MHggPSBkYXRhOworCWlu
dCBzdGF0dXMsIHNocnQsIHJlcG9ydCA9IDA7CisKKwlzdGF0dXMgPSBwbTg2MHhfcmVnX3JlYWQo
cG04NjB4LT5pMmMsIFJFR19TVEFUVVNfMSk7CisJc2hydCA9IHBtODYweF9yZWdfcmVhZChwbTg2
MHgtPmkyYywgUkVHX1NIT1JUUyk7CisKKwlpZiAoc3RhdHVzICYgSEVBRFNFVF9TVEFUVVMpCisJ
CXJlcG9ydCB8PSBQTTg2MFhfREVUX0hFQURTRVQ7CisJaWYgKHN0YXR1cyAmIE1JQ19TVEFUVVMp
CisJCXJlcG9ydCB8PSBQTTg2MFhfREVUX01JQzsKKwlpZiAoc3RhdHVzICYgSE9PS19TVEFUVVMp
CisJCXJlcG9ydCB8PSBQTTg2MFhfREVUX0hPT0s7CisJaWYgKHNocnQgJiAoU0hPUlRfTE8xIHwg
U0hPUlRfTE8yKSkKKwkJcmVwb3J0IHw9IFBNODYwWF9TSE9SVF9MSU5FT1VUOworCWlmIChzaHJ0
ICYgKFNIT1JUX0hTMSB8IFNIT1JUX0hTMikpCisJCXJlcG9ydCB8PSBQTTg2MFhfU0hPUlRfSEVB
RFNFVDsKKwlkZXZfZGJnKHBtODYweC0+Y29kZWMtPmRldiwgInJlcG9ydDoweCV4XG4iLCByZXBv
cnQpOworCXJldHVybiBJUlFfSEFORExFRDsKK30KKworc3RhdGljIGludCBwbTg2MHhfcHJvYmUo
c3RydWN0IHNuZF9zb2NfY29kZWMgKmNvZGVjKQoreworCXN0cnVjdCBwbTg2MHhfcHJpdiAqcG04
NjB4ID0gc25kX3NvY19jb2RlY19nZXRfZHJ2ZGF0YShjb2RlYyk7CisJaW50IGksIHJldDsKKwor
CXBtODYweC0+Y29kZWMgPSBjb2RlYzsKKworCWNvZGVjLT5jb250cm9sX2RhdGEgPSBwbTg2MHgt
PmkyYzsKKworCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHsKKwkJcmV0ID0gcmVxdWVzdF90aHJl
YWRlZF9pcnEocG04NjB4LT5pcnFbaV0sIE5VTEwsCisJCQkJCSAgIHBtODYweF9jb2RlY19oYW5k
bGVyLCBJUlFGX09ORVNIT1QsCisJCQkJCSAgIHBtODYweC0+bmFtZVtpXSwgcG04NjB4KTsKKwkJ
aWYgKHJldCA8IDApIHsKKwkJCWRldl9lcnIoY29kZWMtPmRldiwgIkZhaWxlZCB0byByZXF1ZXN0
IElSUSFcbiIpOworCQkJZ290byBvdXRfaXJxOworCQl9CisJfQorCisJcG04NjB4X3NldF9iaWFz
X2xldmVsKGNvZGVjLCBTTkRfU09DX0JJQVNfU1RBTkRCWSk7CisKKwlyZXQgPSBwbTg2MHhfYnVs
a19yZWFkKGNvZGVjLT5jb250cm9sX2RhdGEsIFJFR19DQUNIRV9CQVNFLAorCQkJICAgICAgIFJF
R19DQUNIRV9TSVpFLCBjb2RlYy0+cmVnX2NhY2hlKTsKKwlpZiAocmV0IDwgMCkgeworCQlkZXZf
ZXJyKGNvZGVjLT5kZXYsICJGYWlsZWQgdG8gZmlsbCByZWdpc3RlciBjYWNoZTogJWRcbiIsCisJ
CQlyZXQpOworCQlnb3RvIG91dF9jb2RlYzsKKwl9CisKKwlzbmRfc29jX2FkZF9jb250cm9scyhj
b2RlYywgcG04NjB4X3NuZF9jb250cm9scywKKwkJCSAgICAgQVJSQVlfU0laRShwbTg2MHhfc25k
X2NvbnRyb2xzKSk7CisJc25kX3NvY19kYXBtX25ld19jb250cm9scyhjb2RlYywgcG04NjB4X2Rh
cG1fd2lkZ2V0cywKKwkJCQkgIEFSUkFZX1NJWkUocG04NjB4X2RhcG1fd2lkZ2V0cykpOworCXNu
ZF9zb2NfZGFwbV9hZGRfcm91dGVzKGNvZGVjLCBhdWRpb19tYXAsIEFSUkFZX1NJWkUoYXVkaW9f
bWFwKSk7CisJcmV0dXJuIDA7CisKK291dF9jb2RlYzoKKwlpID0gMzsKK291dF9pcnE6CisJZm9y
ICg7IGkgPj0gMDsgaS0tKQorCQlmcmVlX2lycShwbTg2MHgtPmlycVtpXSwgcG04NjB4KTsKKwly
ZXR1cm4gLUVJTlZBTDsKK30KKworc3RhdGljIGludCBwbTg2MHhfcmVtb3ZlKHN0cnVjdCBzbmRf
c29jX2NvZGVjICpjb2RlYykKK3sKKwlzdHJ1Y3QgcG04NjB4X3ByaXYgKnBtODYweCA9IHNuZF9z
b2NfY29kZWNfZ2V0X2RydmRhdGEoY29kZWMpOworCWludCBpOworCisJZm9yIChpID0gMzsgaSA+
PSAwOyBpLS0pCisJCWZyZWVfaXJxKHBtODYweC0+aXJxW2ldLCBwbTg2MHgpOworCXBtODYweF9z
ZXRfYmlhc19sZXZlbChjb2RlYywgU05EX1NPQ19CSUFTX09GRik7CisJcmV0dXJuIDA7Cit9CisK
K3N0YXRpYyBzdHJ1Y3Qgc25kX3NvY19jb2RlY19kcml2ZXIgc29jX2NvZGVjX2Rldl9wbTg2MHgg
PSB7CisJLnByb2JlCQk9IHBtODYweF9wcm9iZSwKKwkucmVtb3ZlCQk9IHBtODYweF9yZW1vdmUs
CisJLnJlYWQJCT0gcG04NjB4X3JlYWRfcmVnX2NhY2hlLAorCS53cml0ZQkJPSBwbTg2MHhfd3Jp
dGVfcmVnX2NhY2hlLAorCS5yZWdfY2FjaGVfc2l6ZQk9IFJFR19DQUNIRV9TSVpFLAorCS5yZWdf
d29yZF9zaXplCT0gc2l6ZW9mKHU4KSwKKwkuc2V0X2JpYXNfbGV2ZWwJPSBwbTg2MHhfc2V0X2Jp
YXNfbGV2ZWwsCit9OworCitzdGF0aWMgaW50IF9fZGV2aW5pdCBwbTg2MHhfY29kZWNfcHJvYmUo
c3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcG04NjB4X2NoaXAgKmNo
aXAgPSBkZXZfZ2V0X2RydmRhdGEocGRldi0+ZGV2LnBhcmVudCk7CisJc3RydWN0IHBtODYweF9w
cml2ICpwbTg2MHg7CisJc3RydWN0IHJlc291cmNlICpyZXM7CisJaW50IGksIHJldDsKKworCXBt
ODYweCA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCBwbTg2MHhfcHJpdiksIEdGUF9LRVJORUwpOwor
CWlmIChwbTg2MHggPT0gTlVMTCkKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlwbTg2MHgtPmNoaXAg
PSBjaGlwOworCXBtODYweC0+aTJjID0gKGNoaXAtPmlkID09IENISVBfUE04NjA3KSA/IGNoaXAt
PmNsaWVudAorCQkJOiBjaGlwLT5jb21wYW5pb247CisJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRl
diwgcG04NjB4KTsKKworCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHsKKwkJcmVzID0gcGxhdGZv
cm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfSVJRLCBpKTsKKwkJaWYgKCFyZXMpIHsK
KwkJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBnZXQgSVJRIHJlc291cmNlc1xuIik7
CisJCQlnb3RvIG91dDsKKwkJfQorCQlwbTg2MHgtPmlycVtpXSA9IHJlcy0+c3RhcnQgKyBjaGlw
LT5pcnFfYmFzZTsKKwkJc3RybmNweShwbTg2MHgtPm5hbWVbaV0sIHJlcy0+bmFtZSwgTUFYX05B
TUVfTEVOKTsKKwl9CisKKwlyZXQgPSBzbmRfc29jX3JlZ2lzdGVyX2NvZGVjKCZwZGV2LT5kZXYs
ICZzb2NfY29kZWNfZGV2X3BtODYweCwKKwkJCQkgICAgIHBtODYweF9kYWksIEFSUkFZX1NJWkUo
cG04NjB4X2RhaSkpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiRmFpbGVk
IHRvIHJlZ2lzdGVyIGNvZGVjXG4iKTsKKwkJZ290byBvdXQ7CisJfQorCXJldHVybiByZXQ7CisK
K291dDoKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBOVUxMKTsKKwlrZnJlZShwbTg2MHgp
OworCXJldHVybiAtRUlOVkFMOworfQorCitzdGF0aWMgaW50IF9fZGV2ZXhpdCBwbTg2MHhfY29k
ZWNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IHBtODYw
eF9wcml2ICpwbTg2MHggPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKworCXNuZF9zb2Nf
dW5yZWdpc3Rlcl9jb2RlYygmcGRldi0+ZGV2KTsKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2
LCBOVUxMKTsKKwlrZnJlZShwbTg2MHgpOworCXJldHVybiAwOworfQorCitzdGF0aWMgc3RydWN0
IHBsYXRmb3JtX2RyaXZlciBwbTg2MHhfY29kZWNfZHJpdmVyID0geworCS5kcml2ZXIJPSB7CisJ
CS5uYW1lCT0gIjg4cG04NjB4LWNvZGVjIiwKKwkJLm93bmVyCT0gVEhJU19NT0RVTEUsCisJfSwK
KwkucHJvYmUJPSBwbTg2MHhfY29kZWNfcHJvYmUsCisJLnJlbW92ZQk9IF9fZGV2ZXhpdF9wKHBt
ODYweF9jb2RlY19yZW1vdmUpLAorfTsKKworc3RhdGljIF9faW5pdCBpbnQgcG04NjB4X2luaXQo
dm9pZCkKK3sKKwlyZXR1cm4gcGxhdGZvcm1fZHJpdmVyX3JlZ2lzdGVyKCZwbTg2MHhfY29kZWNf
ZHJpdmVyKTsKK30KK21vZHVsZV9pbml0KHBtODYweF9pbml0KTsKKworc3RhdGljIF9fZXhpdCB2
b2lkIHBtODYweF9leGl0KHZvaWQpCit7CisJcGxhdGZvcm1fZHJpdmVyX3VucmVnaXN0ZXIoJnBt
ODYweF9jb2RlY19kcml2ZXIpOworfQorbW9kdWxlX2V4aXQocG04NjB4X2V4aXQpOworCitNT0RV
TEVfREVTQ1JJUFRJT04oIkFTb0MgODhQTTg2MHggZHJpdmVyIik7CitNT0RVTEVfQVVUSE9SKCJI
YW9qaWFuIFpodWFuZyA8aGFvamlhbi56aHVhbmdAbWFydmVsbC5jb20+Iik7CitNT0RVTEVfTElD
RU5TRSgiR1BMIik7CitNT0RVTEVfQUxJQVMoInBsYXRmb3JtOjg4cG04NjB4LWNvZGVjIik7CisK
ZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy9jb2RlY3MvODhwbTg2MHgtY29kZWMuaCBiL3NvdW5kL3Nv
Yy9jb2RlY3MvODhwbTg2MHgtY29kZWMuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAw
MDAwLi5iMDM0ZGUyCi0tLSAvZGV2L251bGwKKysrIGIvc291bmQvc29jL2NvZGVjcy84OHBtODYw
eC1jb2RlYy5oCkBAIC0wLDAgKzEsOTIgQEAKKy8qCisgKiA4OHBtODYweC1jb2RlYy5oIC0tIDg4
UE04NjB4IEFMU0EgU29DIEF1ZGlvIERyaXZlcgorICoKKyAqIENvcHlyaWdodCAyMDEwIE1hcnZl
bGwgSW50ZXJuYXRpb25hbCBMdGQuCisgKglIYW9qaWFuIFpodWFuZyA8aGFvamlhbi56aHVhbmdA
bWFydmVsbC5jb20+CisgKgorICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBj
YW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBv
ZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIGFzCisgKiBwdWJsaXNo
ZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqLworCisjaWZuZGVmIF9fODhQ
TTg2MFhfSAorI2RlZmluZSBfXzg4UE04NjBYX0gKKworLyogVGhlIG9mZnNldCBvZiB0aGVzZSBy
ZWdpc3RlcnMgYXJlIDB4YjAgKi8KKyNkZWZpbmUgUE04NjBYX1BDTV9JRkFDRV8xCQkweDAwCisj
ZGVmaW5lIFBNODYwWF9QQ01fSUZBQ0VfMgkJMHgwMQorI2RlZmluZSBQTTg2MFhfUENNX0lGQUNF
XzMJCTB4MDIKKyNkZWZpbmUgUE04NjBYX1BDTV9SQVRFCQkJMHgwMworI2RlZmluZSBQTTg2MFhf
RUNfUEFUSAkJCTB4MDQKKyNkZWZpbmUgUE04NjBYX1NJREVUT05FX0xfR0FJTgkJMHgwNQorI2Rl
ZmluZSBQTTg2MFhfU0lERVRPTkVfUl9HQUlOCQkweDA2CisjZGVmaW5lIFBNODYwWF9TSURFVE9O
RV9TSElGVAkJMHgwNworI2RlZmluZSBQTTg2MFhfQURDX09GRlNFVF8xCQkweDA4CisjZGVmaW5l
IFBNODYwWF9BRENfT0ZGU0VUXzIJCTB4MDkKKyNkZWZpbmUgUE04NjBYX0RNSUNfREVMQVkJCTB4
MGEKKworI2RlZmluZSBQTTg2MFhfSTJTX0lGQUNFXzEJCTB4MGIKKyNkZWZpbmUgUE04NjBYX0ky
U19JRkFDRV8yCQkweDBjCisjZGVmaW5lIFBNODYwWF9JMlNfSUZBQ0VfMwkJMHgwZAorI2RlZmlu
ZSBQTTg2MFhfSTJTX0lGQUNFXzQJCTB4MGUKKyNkZWZpbmUgUE04NjBYX0VRVUFMSVpFUl9OMF8x
CQkweDBmCisjZGVmaW5lIFBNODYwWF9FUVVBTElaRVJfTjBfMgkJMHgxMAorI2RlZmluZSBQTTg2
MFhfRVFVQUxJWkVSX04xXzEJCTB4MTEKKyNkZWZpbmUgUE04NjBYX0VRVUFMSVpFUl9OMV8yCQkw
eDEyCisjZGVmaW5lIFBNODYwWF9FUVVBTElaRVJfRDFfMQkJMHgxMworI2RlZmluZSBQTTg2MFhf
RVFVQUxJWkVSX0QxXzIJCTB4MTQKKyNkZWZpbmUgUE04NjBYX0xPRklfR0FJTl9MRUZUCQkweDE1
CisjZGVmaW5lIFBNODYwWF9MT0ZJX0dBSU5fUklHSFQJCTB4MTYKKyNkZWZpbmUgUE04NjBYX0hJ
RklMX0dBSU5fTEVGVAkJMHgxNworI2RlZmluZSBQTTg2MFhfSElGSUxfR0FJTl9SSUdIVAkJMHgx
OAorI2RlZmluZSBQTTg2MFhfSElGSVJfR0FJTl9MRUZUCQkweDE5CisjZGVmaW5lIFBNODYwWF9I
SUZJUl9HQUlOX1JJR0hUCQkweDFhCisjZGVmaW5lIFBNODYwWF9EQUNfT0ZGU0VUCQkweDFiCisj
ZGVmaW5lIFBNODYwWF9PRkZTRVRfTEVGVF8xCQkweDFjCisjZGVmaW5lIFBNODYwWF9PRkZTRVRf
TEVGVF8yCQkweDFkCisjZGVmaW5lIFBNODYwWF9PRkZTRVRfUklHSFRfMQkJMHgxZQorI2RlZmlu
ZSBQTTg2MFhfT0ZGU0VUX1JJR0hUXzIJCTB4MWYKKyNkZWZpbmUgUE04NjBYX0FEQ19BTkFfMQkJ
MHgyMAorI2RlZmluZSBQTTg2MFhfQURDX0FOQV8yCQkweDIxCisjZGVmaW5lIFBNODYwWF9BRENf
QU5BXzMJCTB4MjIKKyNkZWZpbmUgUE04NjBYX0FEQ19BTkFfNAkJMHgyMworI2RlZmluZSBQTTg2
MFhfQU5BX1RPX0FOQQkJMHgyNAorI2RlZmluZSBQTTg2MFhfSFMxX0NUUkwJCQkweDI1CisjZGVm
aW5lIFBNODYwWF9IUzJfQ1RSTAkJCTB4MjYKKyNkZWZpbmUgUE04NjBYX0xPMV9DVFJMCQkJMHgy
NworI2RlZmluZSBQTTg2MFhfTE8yX0NUUkwJCQkweDI4CisjZGVmaW5lIFBNODYwWF9FQVJfQ1RS
TF8xCQkweDI5CisjZGVmaW5lIFBNODYwWF9FQVJfQ1RSTF8yCQkweDJhCisjZGVmaW5lIFBNODYw
WF9BVURJT19TVVBQTElFU18xCQkweDJiCisjZGVmaW5lIFBNODYwWF9BVURJT19TVVBQTElFU18y
CQkweDJjCisjZGVmaW5lIFBNODYwWF9BRENfRU5fMQkJCTB4MmQKKyNkZWZpbmUgUE04NjBYX0FE
Q19FTl8yCQkJMHgyZQorI2RlZmluZSBQTTg2MFhfREFDX0VOXzEJCQkweDJmCisjZGVmaW5lIFBN
ODYwWF9EQUNfRU5fMgkJCTB4MzEKKyNkZWZpbmUgUE04NjBYX0FVRElPX0NBTF8xCQkweDMyCisj
ZGVmaW5lIFBNODYwWF9BVURJT19DQUxfMgkJMHgzMworI2RlZmluZSBQTTg2MFhfQVVESU9fQ0FM
XzMJCTB4MzQKKyNkZWZpbmUgUE04NjBYX0FVRElPX0NBTF80CQkweDM1CisjZGVmaW5lIFBNODYw
WF9BVURJT19DQUxfNQkJMHgzNgorI2RlZmluZSBQTTg2MFhfQU5BX0lOUFVUX1NFTF8xCQkweDM3
CisjZGVmaW5lIFBNODYwWF9BTkFfSU5QVVRfU0VMXzIJCTB4MzgKKworI2RlZmluZSBQTTg2MFhf
UENNX0lGQUNFXzQJCTB4MzkKKyNkZWZpbmUgUE04NjBYX0kyU19JRkFDRV81CQkweDNhCisKKyNk
ZWZpbmUgUE04NjBYX1NIT1JUUwkJCTB4M2IKKyNkZWZpbmUgUE04NjBYX1BMTF9BREpfMQkJMHgz
YworI2RlZmluZSBQTTg2MFhfUExMX0FESl8yCQkweDNkCisKKy8qIGJpdHMgZGVmaW5pdGlvbiAq
LworI2RlZmluZSBQTTg2MFhfQ0xLX0RJUl9JTgkJMAorI2RlZmluZSBQTTg2MFhfQ0xLX0RJUl9P
VVQJCTEKKworI2RlZmluZSBQTTg2MFhfREVUX0hFQURTRVQJCSgxIDw8IDApCisjZGVmaW5lIFBN
ODYwWF9ERVRfTUlDCQkJKDEgPDwgMSkKKyNkZWZpbmUgUE04NjBYX0RFVF9IT09LCQkJKDEgPDwg
MikKKyNkZWZpbmUgUE04NjBYX1NIT1JUX0hFQURTRVQJCSgxIDw8IDMpCisjZGVmaW5lIFBNODYw
WF9TSE9SVF9MSU5FT1VUCQkoMSA8PCA0KQorI2RlZmluZSBQTTg2MFhfREVUX01BU0sJCQkweDFG
CisKKyNlbmRpZgkvKiBfXzg4UE04NjBYX0ggKi8KZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy9jb2Rl
Y3MvS2NvbmZpZyBiL3NvdW5kL3NvYy9jb2RlY3MvS2NvbmZpZwppbmRleCBiZmRkOTJiLi5hM2Nm
YzE4IDEwMDY0NAotLS0gYS9zb3VuZC9zb2MvY29kZWNzL0tjb25maWcKKysrIGIvc291bmQvc29j
L2NvZGVjcy9LY29uZmlnCkBAIC0xMCw2ICsxMCw3IEBAIGNvbmZpZyBTTkRfU09DX0kyQ19BTkRf
U1BJCiAKIGNvbmZpZyBTTkRfU09DX0FMTF9DT0RFQ1MKIAl0cmlzdGF0ZSAiQnVpbGQgYWxsIEFT
b0MgQ09ERUMgZHJpdmVycyIKKwlzZWxlY3QgU05EX1NPQ184OFBNODYwWCBpZiBNRkRfODhQTTg2
MFgKIAlzZWxlY3QgU05EX1NPQ19MMwogCXNlbGVjdCBTTkRfU09DX0FDOTdfQ09ERUMgaWYgU05E
X1NPQ19BQzk3X0JVUwogCXNlbGVjdCBTTkRfU09DX0FEMTgzNiBpZiBTUElfTUFTVEVSCkBAIC04
NSw2ICs4Niw5IEBAIGNvbmZpZyBTTkRfU09DX0FMTF9DT0RFQ1MKIAogICAgICAgICAgIElmIHVu
c3VyZSBzZWxlY3QgIk4iLgogCitjb25maWcgU05EX1NPQ184OFBNODYwWAorCXRyaXN0YXRlCisK
IGNvbmZpZyBTTkRfU09DX1dNX0hVQlMKIAl0cmlzdGF0ZQogCWRlZmF1bHQgeSBpZiBTTkRfU09D
X1dNODk5Mz15IHx8IFNORF9TT0NfV004OTk0PXkKZGlmZiAtLWdpdCBhL3NvdW5kL3NvYy9jb2Rl
Y3MvTWFrZWZpbGUgYi9zb3VuZC9zb2MvY29kZWNzL01ha2VmaWxlCmluZGV4IDljM2MzOWYuLmI5
YzQzNTggMTAwNjQ0Ci0tLSBhL3NvdW5kL3NvYy9jb2RlY3MvTWFrZWZpbGUKKysrIGIvc291bmQv
c29jL2NvZGVjcy9NYWtlZmlsZQpAQCAtMSwzICsxLDQgQEAKK3NuZC1zb2MtODhwbTg2MHgtb2Jq
cyA6PSA4OHBtODYweC1jb2RlYy5vCiBzbmQtc29jLWFjOTctb2JqcyA6PSBhYzk3Lm8KIHNuZC1z
b2MtYWQxODM2LW9ianMgOj0gYWQxODM2Lm8KIHNuZC1zb2MtYWQxOTN4LW9ianMgOj0gYWQxOTN4
Lm8KQEAgLTY3LDYgKzY4LDcgQEAgc25kLXNvYy10cGE2MTMwYTItb2JqcyA6PSB0cGE2MTMwYTIu
bwogc25kLXNvYy13bTIwMDAtb2JqcyA6PSB3bTIwMDAubwogc25kLXNvYy13bTkwOTAtb2JqcyA6
PSB3bTkwOTAubwogCitvYmotJChDT05GSUdfU05EX1NPQ184OFBNODYwWCkJKz0gc25kLXNvYy04
OHBtODYweC5vCiBvYmotJChDT05GSUdfU05EX1NPQ19BQzk3X0NPREVDKQkrPSBzbmQtc29jLWFj
OTcubwogb2JqLSQoQ09ORklHX1NORF9TT0NfQUQxODM2KQkrPSBzbmQtc29jLWFkMTgzNi5vCiBv
YmotJChDT05GSUdfU05EX1NPQ19BRDE5M1gpCSs9IHNuZC1zb2MtYWQxOTN4Lm8KLS0gCjEuNS42
LjUKCg==
--0016e6d63f44021a1f048e002b69--
1
0