From mboxrd@z Thu Jan 1 00:00:00 1970 From: haojian.zhuang@marvell.com (Haojian Zhuang) Date: Thu, 12 Aug 2010 12:01:47 +0800 Subject: [PATCH 1/3] ASoC: add 88pm860x codec driver Message-ID: To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Add 88PM860x codec driver. 88PM860x codec supports two interfaces. And it also supports headset/mic/hook/short detection. Signed-off-by: Haojian Zhuang --- 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +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 + * + * 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--